两张图片合并(右上角添加水印,兼容矢量图)保留原来的颜色

news2024/11/17 13:34:45

无缝合并两张图片(封面右上角添加logo)-- opencv : 进行添加logo(水印)由于使用了cv2.seamlessClonecv2.seamlessClone使用了泊松克隆(Poisson Cloning),会根据周围的颜色信息进行颜色调整,使得融合后的区域更加自然,但这也可能导致颜色发生变化。

在这里插入图片描述
logo 都花了,颜色也不对了。
为了保留原来的颜色,可以使用简单的覆盖方法而不是cv2.seamlessClone

import os
import cv2
import sys
import traceback
import numpy as np
import requests
import logging





def get_logoUrl(logoUrl, uid):
    """
        Download logo image from URL and save it locally.

        Args:
        - logoUrl (str): URL of the logo image.
        - uid (str): Unique identifier for the image.

        Returns:
        - str: File path where the logo image is saved.
        """
    end = logoUrl.split('.')[-1]
    content = requests.get(logoUrl).content
    #logger.info(os.getcwd())
    try:
        logo_name = f'logo_images/{uid}.{end}'
        #logger.info(logo_name)
        print(logo_name)
        #print(os.getcwd())
        with open(logo_name,'wb') as f:
            f.write(content)
        return logo_name
    except:
        #logger.info(traceback.format_exc())
        print(traceback.format_exc())
        # return dict(code=10099, data='系统未能获得有效结果,请稍后重试')



def merge_logo2First_page(uid, logoUrl):
    """
       Merge a logo onto the first page image, preserving transparency if present.

       Args:
       - uid (str): Unique identifier for the image.
       - logoUrl (str): URL of the logo image.

       Returns:
       - str: File path where the merged image is saved.
       """
    folder = 'imgs/'

    # 获取 logo 图片
    logo_name = get_logoUrl(logoUrl, uid)
    obj = cv2.imread(logo_name, cv2.IMREAD_UNCHANGED)

    if obj is None:
        raise ValueError(f"Image at path {logo_name} could not be read.")

    (h, w, z) = obj.shape

    # 固定 logo 图片的大小
    obj_fixed_size = cv2.resize(obj, (round(200 * (w / h)), 200))
    (h, w, z) = obj_fixed_size.shape

    # 检查是否存在 Alpha 通道,如果没有则创建一个全白的 Alpha 通道
    if obj_fixed_size.shape[2] == 4:
        alpha_channel = obj_fixed_size[:, :, 3] / 255.0
        obj_rgb = obj_fixed_size[:, :, :3]
    else:
        alpha_channel = np.ones((obj_fixed_size.shape[0], obj_fixed_size.shape[1]), dtype=np.float32)
        obj_rgb = obj_fixed_size

    # 读取主图片
    im = cv2.imread(folder + "auto_first_page.jpg")
    (height, width, channels) = im.shape

    # 计算 logo 的放置位置(右上角)
    top_left_h = 100  # 距离顶部的距离
    top_left_w = width - w - 222  # 距离右侧的距离

    # 边界检查,确保放置位置在主图片内
    if top_left_h < 0:
        top_left_h = 0
    if top_left_w < 0:
        top_left_w = 0
    if top_left_h + h > height:
        top_left_h = height - h
    if top_left_w + w > width:
        top_left_w = width - w

    # 处理透明度,将有颜色的部分覆盖到主图片上
    # for c in range(0, 3):
    #     im[top_left_h:top_left_h + h, top_left_w:top_left_w + w, c] = (
    #             alpha_channel * obj_rgb[:, :, c] +
    #             (1 - alpha_channel) * im[top_left_h:top_left_h + h, top_left_w:top_left_w + w, c]
    #     )
    # 矩阵计算替代显式循环:使用 NumPy 的广播功能,将显式循环转换为矩阵计算,从而提高效率。
    im[top_left_h:top_left_h + h, top_left_w:top_left_w + w, :3] = (
            (alpha_channel[..., np.newaxis] * obj_rgb) +
            ((1 - alpha_channel[..., np.newaxis]) * im[top_left_h:top_left_h + h, top_left_w:top_left_w + w, :3])
    )
    # 保存处理后的图片
    save_path = 'first_page_merged_logo/'
    if not os.path.exists(save_path):
        os.makedirs(save_path)

    output_path = os.path.join(save_path, f"merged_{uid}.jpg")
    cv2.imwrite(output_path, im)

    return output_path, logo_name


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

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

相关文章

基于单片机的饲料搅拌机控制系统设计

摘要 &#xff1a; 文章主要从软件和硬件两个部分对基于单片机的饲料搅拌机控制系统进行研究设计 。 硬件部分主要由传感器模块 、 信号采集模块、 键盘接入模块 、 LED 显示模块 、 继电器模块以及看门狗模块组成 。 软件部分在 KeilC51 软件基础上重点对控制系统主程序 、…

Android - 云游戏本地悬浮输入框实现

一、简述 云游戏输入法分两种情况,以云化原神为例,分为 云端输入法 和 本地输入法,运行效果如下: 云端输入法本地输入法云端输入法 就是运行在云端设备上的输入法,对于不同客户端来说(Android、iPhone),运行效果一致。 本地输入法 则是运行在用户侧设备上的输入法,对…

sizeof跟strlen的用法及差异

sizeof是一个操作符&#xff0c;不是函数&#xff1b; 而strlen是一个库函数&#xff1b; sizeof是计算所占内存空间的&#xff0c;不管你内容是什么&#xff0c;只要知道占多少内存&#xff0c; 而strlen是跟内容有关的&#xff0c;它是计算字符串长度的&#xff08;字符数…

vue学习day01-vue的概念、创建Vue实例、插值表达式、响应式、安装Vue开发者工具

1、vue的概念 Vue是一个用于构建用户界面的渐进式 框架 &#xff08;1&#xff09;构建用户界面&#xff1a;基于数据动态渲染页面 &#xff08;2&#xff09;渐进式&#xff1a;循序渐进的学习 &#xff08;3&#xff09;框架&#xff1a;一条完整的项目解决方案&#xff…

[Java]Swing版坦克大战小游戏项目开发(1)——new出一个窗口

highlight: xcode theme: vuepress 前言 本系列文章带领 Java 初学者学习使用 Java 语言结合 Swing 技术以及设计模式开发一款经典小游戏——坦克大战。通过这个小游戏&#xff0c;你可以学会很多实用的设计模式思想&#xff0c;并且提高你的编码水平。 熟悉Frame Frame 类是 J…

C++ | Leetcode C++题解之第224题计算计算器

题目&#xff1a; 题解&#xff1a; class Solution { public:int calculate(string s) {stack<int> ops;ops.push(1);int sign 1;int ret 0;int n s.length();int i 0;while (i < n) {if (s[i] ) {i;} else if (s[i] ) {sign ops.top();i;} else if (s[i] …

亚马逊erp同步订单自动发货,告别手动,批量自动发货流...

大家好&#xff0c;今天讲下店飞飞订单之后如何让它自动发货。批量自动发货点开ERP上的订单&#xff0c;比如每天出个几十单爆单就最好的。订单跟ERP上配对成功不需要手动发货&#xff0c;自动发货都是批量发货&#xff0c;就不用一个个去点了。 那就讲下怎么设置的。 点开品…

【面试八股总结】线程基本概念,线程、进程和协程区别,线程实现

一、什么是线程&#xff1f; 线程是“轻量级进程”&#xff0c;是进程中的⼀个实体&#xff0c;是程序执⾏的最小单元&#xff0c;也是被系统独立调度和分配的基本单位。 线程是进程当中的⼀条执行流程&#xff0c;同⼀个进程内多个线程之间可以共享代码段、数据段、打开的文件…

Linux: 命令行参数和环境变量究竟是什么?

Linux: 命令行参数和环境变量究竟是什么&#xff1f; 一、命令行参数1.1 main函数参数意义1.2 命令行参数概念1.3 命令行参数实例 二、环境变量2.1 环境变量概念2.2 环境变量&#xff1a;PATH2.2.1 如何查看PATH中的内容2.2.2 如何让自己的可执行文件不带路径运行 2.3 环境变量…

科普文:K8S中常见知识点梳理

简单说一下k8s集群内外网络如何互通的 要在 Kubernetes&#xff08;k8s&#xff09;集群内外建立网络互通&#xff0c;可以采取以下措施&#xff1a; 使用service&#xff1a; 使用Service类型为NodePort或LoadBalancer的Kubernetes服务。这可以使服务具有一个公共IP地址或端口…

Java面试八股之MySQL中int(10)和bigint(10)能存储读的数据大小一样吗

MySQL中int(10)和bigint(10)能存储读的数据大小一样吗 在MySQL中&#xff0c;int(10)和bigint(10)的数据存储能力并不相同&#xff0c;尽管括号内的数字&#xff08;如10&#xff09;看起来似乎暗示着某种关联&#xff0c;但实际上这个数字代表的是显示宽度&#xff0c;而不是…

深入讲解C++基础知识(三)

目录 一、命名空间1. 创建命名空间2. 访问命名空间2.1 using 编译指令2.2 using 声明2.3 直接使用全名 3. 嵌套命名空间4. 匿名命名空间5. 命名空间的注意事项5.1 头文件中不应该包含 using 声明和 using 编译指令。5.2 最好使用 using 声明而不是 using 编译指令 二、标准库类…

LiveNVR监控流媒体Onvif/RTSP用户手册-录像计划:批量配置、单个配置、录像保存(天)、配置时间段录像

TOC 1、录像计划 支持单个通道 或是 通道范围内配置支持快速滑选支持录像时间段配置 1.1、录像存储位置如何配置&#xff1f; 2、RTSP/HLS/FLV/RTMP拉流Onvif流媒体服务 支持 Windows Linux 及其它CPU架构&#xff08;国产、嵌入式…&#xff09;操作系统安装包下载 、 安装…

Kubernetes平台迁移

Kubernetes&&平台迁移 信息收集 信息收集

浅析Nginx技术:开源高性能Web服务器与反向代理

什么是Nginx&#xff1f; Nginx是一款轻量级、高性能的HTTP和反向代理服务器&#xff0c;也可以用作邮件代理服务器。它最初由俄罗斯的程序员Igor Sysoev在2004年开发&#xff0c;并于2004年首次公开发布。Nginx的主要优势在于其非阻塞的事件驱动架构&#xff0c;能够处理大量并…

128陷阱详解(从源码分析)

1、128陷阱描述 Integer 整型 -128~127 超过这个范围&#xff0c;比较会不准确 例子 public static void main(String[] args) {Integer a128;Integer b128;Integer e127;Integer f127;System.out.println(ab); //输出falseSystem.out.println(a.equals(b)); //输出trueS…

小程序做自定义分享封面图,Canvas base64图片数据真机上不显示?【已解决】

首选说一下需求&#xff0c;做一个小程序分享&#xff0c;但是封面图要自定义&#xff0c;除了要有对应商品还有有背景图&#xff0c;商品名。类似这种 实现逻辑&#xff0c;把商品图和背景图&#xff0c;再加上价格和商品名用canvas 渲染出来 这是弄好之后的效果图&#xff0…

LeetCode-刷题记录-前缀和合集(本篇blog会持续更新哦~)

一、前缀和&#xff08;Prefix Sum&#xff09;算法概述 前缀和算法通过预先计算数组的累加和&#xff0c;可以在常数时间内回答多个区间和相关的查询问题&#xff0c;是解决子数组和问题中的重要工具。 它的基本思想是通过预先计算和存储数组的前缀和&#xff0c;可以在 O(1)…

NCCL 中的一些辅助debug 知识点

1&#xff0c;调试nccl 启动kernel的方法 ncclLaunchKernel cuLaunchKernelEx ncclStrongStreamLaunchKernel cudaLaunchKernel ncclLaunchOneRank cudaLaunchKernel 在 nccl lib 中&#xff0c;不存在使用<<<grid, block,,>>> 这种类似方式启…