(OpenCV)图片拼接

前言

        图片拼接在许多领域都有广泛的应用,包括但不限于以下几个方面:

  1. 全景摄影:在摄影中,通过将多张照片拼接在一起可以实现全景照片的效果。这在旅游景点、房地产展示等领域有着广泛的应用,能够提供更加生动、真实的视觉体验。

  2. 医学影像处理:在医学影像领域,例如 CT、MRI 等影像数据的拼接可以帮助医生获取更加完整的患者信息,进而进行更精确的诊断和治疗计划制定。

  3. 地图制作:地图制作中常常需要将多个局部地图或航拍影像拼接成较大范围的地图,以满足城市规划、导航、军事应用等领域的需求。

  4. 无人机航拍:在无人机航拍领域,通过将无人机航拍获取的多张照片进行拼接,可以生成更加细致和全面的航拍影像,用于农业、环境监测、工程测绘等领域。

  5. 虚拟现实(VR)和增强现实(AR):在虚拟现实和增强现实技术中,图片拼接可以用来创建虚拟环境或增强真实环境,提供更加沉浸式的体验。

  6. 文物修复和数字化:在文物保护领域,通过对文物的多角度拍摄并进行拼接,可以实现对文物的三维重建和数字化保存,以及对文物进行修复和研究。

代码

重叠拼接

将相同位置的图片进行叠加

import cv2
import numpy as np


# 加载图片
image1 = cv2.imread('D:\\sucai\\image1.png')
image2 = cv2.imread('D:\\sucai\\image2.png')

save_img = 'D:\\sucai\\merge_image_simple.png'
# 确定目标图像大小
height = max(image1.shape[0], image2.shape[0])
width = max(image1.shape[1], image2.shape[1])
target_image = np.zeros((height, width, 3), dtype=np.uint8)
# 叠加图片
target_image[:image1.shape[0], :image1.shape[1]] = image1
target_image[:image2.shape[0], :image2.shape[1]] += image2  # 叠加在同一位置

# 显示结果
cv2.imshow('Simple Blend', target_image)
cv2.imwrite(save_img, target_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

重叠拼接(加权)

在OpenCV中,cv2.addWeighted()函数可以用来对两幅图像进行加权相加,产生一幅新的图像

通过调整alphabeta的值,可以控制不同图像在最终混合结果中所占比重,从而实现不同的混合效果。

import cv2

# 读取两幅图像
img_path_list = ['D:\\sucai\\image1.png', 'D:\\sucai\\image2.png']
image_obj_list = [cv2.imread(i) for i in img_path_list]
w_list = [i.shape[0] for i in image_obj_list]
h_list = [i.shape[1] for i in image_obj_list]
w_max = max(w_list)
h_max = max(h_list)
image_obj_list = [cv2.resize(i, (w_max, h_max)) for i in image_obj_list]
# 设置权重参数
"""
src1:第一幅输入图像。
alpha:第一幅图像的权重。
src2:第二幅输入图像。
beta:第二幅图像的权重。
gamma:一个可选的参数,用于控制加权和的常数值。
"""
alpha = 0.5
beta = 0.5
gamma = 0
# 对两幅图像进行加权相加
merged_image = cv2.addWeighted(image_obj_list[0], alpha, image_obj_list[1], beta, gamma)

# 显示结果
cv2.imshow('Blended Image', merged_image)
cv2.imwrite(save_img, merged_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

水平拼接

import cv2


img_path_list = ['D:\\sucai\\image1.png', 'D:\\sucai\\image2.png']
save_img = 'D:\\sucai\\merge_image.png'
image_obj_list = [cv2.imread(i) for i in img_path_list]
# 获取所有图片的尺寸大小
w_list = [i.shape[0] for i in image_obj_list]
h_list = [i.shape[1] for i in image_obj_list]
w_max = max(w_list)
h_max = max(h_list)
# 统一子图的尺寸大小
image_obj_list = [cv2.resize(i, (w_max, h_max)) for i in image_obj_list]
# 水平拼接
merged_image = cv2.hconcat(image_obj_list)

# 显示合并后的图片
cv2.imshow('Merged Image', merged_image)
# 保存图片
cv2.imwrite(save_img, merged_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

垂直拼接

import cv2


img_path_list = ['D:\\sucai\\image1.png', 'D:\\sucai\\image2.png']
save_img = 'D:\\sucai\\merge_image.png'
image_obj_list = [cv2.imread(i) for i in img_path_list]
# 获取所有图片的尺寸大小
w_list = [i.shape[0] for i in image_obj_list]
h_list = [i.shape[1] for i in image_obj_list]
w_max = max(w_list)
h_max = max(h_list)
# 统一子图的尺寸大小
image_obj_list = [cv2.resize(i, (w_max, h_max)) for i in image_obj_list]
# 垂直拼接
merged_image = cv2.vconcat(image_obj_list)

# 显示合并后的图片
cv2.imshow('Merged Image', merged_image)
# 保存图片
cv2.imwrite(save_img, merged_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

全景拼接

拼接器使用这些重叠区域中的特征点来找到图像间的对应关系。如果重叠区域过小或者不存在,拼接器可能无法找到足够的匹配特征点进行拼接。

import sys
import cv2

img1 = cv2.imread('D:\\sucai\\2\\image1.png')
img2 = cv2.imread('D:\\sucai\\2\\image2.png')

save_img = 'D:\\sucai\\merge_image.png'

# 检查图像是否正确加载
if img1 is None or img2 is None:
    print("其中一个或两个图像加载失败")
    sys.exit()

img_obj = cv2.Stitcher.create(cv2.Stitcher_PANORAMA)
(status, stitched_image) = img_obj.stitch((img1, img2))
if status != cv2.Stitcher_OK:
    print("不能拼接图片, error code = %d" % status)
else:
    print("拼接成功.")
    cv2.imshow('pano', stitched_image)
    cv2.imwrite(save_img, stitched_image)
    cv2.waitKey()
    cv2.destroyAllWindows()
sys.exit()

前景图和背景图拼接

注意:前景图需要作个缩放处理,小于背景图.

 


save_img = 'D:\\sucai\\merge_image.png'
img_list = ['D:\\sucai\\5\\foreground.png', 'D:\\sucai\\5\\background.png']

img_fg = cv2.imread(img_list[0])  # 读取前景图
img_bg = cv2.imread(img_list[1])  # 读取背景图
# 读取背景图和前景图的像素和通道数
rows_bg, cols_bg, channels_bg = img_bg.shape
rows_fg, cols_fg, channels_fg = img_fg.shape

# 为了防止批处理时有可能出现前景图像素尺寸大于背景图的情况,做一个缩小前景图的操作
rows_change_fg = rows_fg // 6
cols_change_fg = cols_fg // 6
# 把前景图缩小
img_fg = cv2.resize(img_fg, (cols_change_fg, rows_change_fg), interpolation=cv2.INTER_LINEAR)
# 选择背景图中对应大小的区域
start_row = 240
start_col = 280
roi = img_bg[start_row:rows_change_fg+start_row, start_col:cols_change_fg+start_col]
# 将前景图转换为灰度图
img_fg2gray = cv2.cvtColor(img_fg, cv2.COLOR_BGR2GRAY)
# 创建掩膜
ret, mask = cv2.threshold(img_fg2gray, 255, 255, cv2.THRESH_BINARY)
# 掩膜取反
mask_inv = cv2.bitwise_not(mask)
# 使用掩膜进行图像合并
img_bg_bg = cv2.bitwise_and(roi, roi, mask=mask)
img_fg_fg = cv2.bitwise_and(img_fg, img_fg, mask=mask_inv)

dst = cv2.add(img_bg_bg, img_fg_fg)
img_bg[start_row:rows_change_fg + start_row, start_col:cols_change_fg+start_col] = dst
cv2.imshow('merge_image', img_bg)
cv2.imwrite(save_img, img_bg)
cv2.waitKey(0)
cv2.destroyAllWindows()

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

uni-app使用uView打开弹出层后输入框聚焦时placeholder错位问题

这里就不放效果了,大概意思就是在使用uView的popus时,在底部弹出后,如果弹窗中的输入框会造成一瞬间的placeholder文字错位,这个问题的主要是因为uView安全区适配导致 uView相关文档 https://www.uviewui.com/components/safeAr…

练习接口测试第一步骤

最近一段时间学了Python语言,重新学了 Java,js,html语言,CSS,linux,一堆测试工具;唉~ 在接触接口测试过程中补了很多课, 终于有点领悟接口测试的根本; 偶是…

笔记 记录

前言 个人记录 官网模版 基于 vue2 示例图

C++初阶:容器适配器介绍、stack和queue常用接口详解及模拟实现

介绍完了list类的相关内容后:C初阶:适合新手的手撕list(模拟实现list) 接下来进入新的篇章,stack和queue的介绍以及模拟: 文章目录 1.stack的初步介绍2.stack的使用3.queue的初步介绍4.queue的使用5.容器适…

gspread,一个超强的 Python 库!

更多Python学习内容:ipengtao.com 大家好,今天为大家分享一个超强的 Python 库 - gspread。 Github地址:https://github.com/burnash/gspread Google Sheets是一款强大的在线电子表格工具,而gspread是一个Python库,可以…

Sentinel从入门到“精通”,从源码层面学习Sentinel

B站视频讲解 文章目录 一、安装1、原生使用2、dashboard整合2-1、非starter整合2-1-1、公共2-1-2、Filter2-1-3、AOP2-2、starter 整合 3、总结 二、常见的策略1、限流1-1、基于QPS 限流1-2、基于线程数限流 2、降级2-1、慢调用比例2-2、异常数(限流异常不算&#x…

C++ 蛇形矩阵的制作

#include <stdio.h>int arr[101][101]; int n; int i,j; int m; int tmp; void Print(){for(i1;i<n;i){for(j1;j<n-i1;j)printf("%d ",arr[i][j]);puts("");} }void fun(){//i j 初值为1i1,j1;//保底用 tmp 1;//计数从1开始m 1;while(1)…

异常—JAVA

文章目录 异常的概念异常的体系结构异常的分类运行时异常 异常的处理防御式编程异常的抛出异常的捕获异常声明throwstry—catch捕获并处理finally 异常的处理流程自定义异常类 异常的概念 首先在学习之前我们要先知道什么是异常&#xff0c;异常简单来说就是不对的地方我们说一…

MySQL DQL 基本查询

一.概念 数据查询不应只是简单返回数据库中存储的数据&#xff0c;还应该根据需要对数据进行筛选以及确定数据以什么样的格式显示。 二.语法格式 select 列名 from 表 where 条件 1.查询所有的商品 select * from product; 2.查询商品名和商品价格 select pname,price from…

Python实现时间序列分析简单指数平滑模型(SimpleExpSmoothing算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 时间序列分析中的简单指数平滑&#xff08;Simple Exponential Smoothing, SES&#xff09;模型是一种…

哈希表——位图

哈希表——位图 基本概念一道面试题位图实现设置存在或不存在检查存在 解决一开始的问题 之前我们已经了解了哈希表的底层实现&#xff0c;今天我们来了解一下哈希表思想的衍生产物——位图。 基本概念 在了解位图之前&#xff0c;我们先来了解一些简单的概念。 我们都知道&a…

控制程序执行流程

资源 资源下载 【免费】突破密码认证程序&#xff08;修改函数返回地址&#xff09;资源-CSDN文库 资源内容 源码 在上一篇文章里 修改函数返回地址-CSDN博客 流程 对程序进行编译 思路 了解栈的情况&#xff08;函数地址、缓冲区偏移量&#xff09;程序中密码认证的地…

力扣 第 385 场周赛 解题报告 | 珂学家 | 字典树专场

前言 整体评价 这是一场字典树专场&#xff0c;除了t3这个小模拟之外&#xff0c;1&#xff0c;2&#xff0c;4皆可用字典树搞定。 T4感觉做法挺多的&#xff0c;其实&#xff0c;但是字典树应该效率最高的。 T1. 统计前后缀下标对 I 思路: 模拟 O ( n 2 ) O(n^2) O(n2)全遍…

D3842——三极管驱动,专为脱线和Dc-Dc开关电源应用设计的,起动电流小

D3842/43/44是专为脱线和Dc-Dc开关电源应用设计的恒频电流型Pwd控制器内部包含温度补偿精密基准、供精密占空比调节用的可调振荡器、高增益混放大器、电流传感比较器和适合作功率MOST驱动用的大电流推挽输出颇以及单周期徊滞式限流欠压锁定、死区可调、单脉冲计数拴锁等保护电路…

【RL】Monte Carlo Learning(蒙特卡洛学习)

Lecture 5: Monte Carlo Learning The simplest MC-based RL algorithm: MC Basic 理解MC basic算法的关键是理解如何将policy iteration算法迁移到model-free的条件下。 Policy iteration算法在每次迭代过程中有两步&#xff1a; { Policy evaluation: v π k r π k γ…

山西电力市场日前价格预测【2024-02-16】

日前价格预测 预测说明&#xff1a; 如上图所示&#xff0c;预测明日&#xff08;2024-02-16&#xff09;山西电力市场全天平均日前电价为55.97元/MWh。其中&#xff0c;最高日前电价为314.75元/MWh&#xff0c;预计出现在18:45。最低日前电价为0.00元/MWh&#xff0c;预计出现…

Conda管理Python不同版本教程

Conda管理Python不同版本教程 目录 0.前提 1.conda常用命令 2.conda管理python库 不太推荐 pyenv管理Python不同版本教程&#xff08;本人另一篇博客&#xff0c;姊妹篇&#xff09; 0.前提 ①anaconda、miniconda&#xff08;2个的下载仓库&#xff09;在win上推荐前者&a…

为什么将二维码分解成文字? 二维码在线转文字的方法

将二维码分解成文字的主要目的是为了方便人们获取二维码中的信息便于使用。二维码是一种由黑白方块组成的图案&#xff0c;可以存储大量的数据&#xff0c;如网址、联系方式、产品信息等。然而&#xff0c;对于一些特定的场景或个人需求&#xff0c;无法直接扫描二维码。因此&a…

ubuntu22.04@laptop OpenCV Get Started: 013_contour_detection

ubuntu22.04laptop OpenCV Get Started: 013_contour_detection 1. 源由2. 应用Demo2.1 C应用Demo2.2 Python应用Demo 3. contour_approx应用3.1 读取图像并将其转换为灰度格式3.2 应用二进制阈值过滤算法3.3 查找对象轮廓3.4 绘制对象轮廓3.5 效果3.6 CHAIN_APPROX_SIMPLE v.s…

vue的生命周期图解

vue的生命周期图解 添加链接描述 vue的生命周期函数及过程的简述&#xff1a; vue的生命周期函数&#xff0c;其实就是vm的生命周期&#xff1b; 创建&#xff1a;beforeCreate、created 挂载&#xff1a;beforeMount、mounted 更新&#xff1a;beforeUpdate、updated [ˌʌpˈ…