再写-全景拼接

news2024/10/6 1:43:07

全景拼接

1. 将读取进行灰度转化,并且输出图像,关键点和计算描述

import cv2
import numpy as np

# 将读取进行灰度转化,并且输出图像,关键点和计算描述
image_left = cv2.imread("C:\\Users\\HONOR\\Desktop\\image\\pinjie_1.png")
image_right = cv2.imread("C:\\Users\\HONOR\\Desktop\\image\\pinjie_2.png")
imge_letf = cv2.resize(image_left, (image_right.shape[1], image_left.shape[0]))
print(imge_letf.shape)
# 图像灰度化
image_left_gray = cv2.cvtColor(image_left, cv2.COLOR_RGB2GRAY)
image_right_gray = cv2.cvtColor(image_right, cv2.COLOR_RGB2GRAY)
# 创建sift对象
sift = cv2.SIFT_create()
# 计算关键点
kp_left, des_left = sift.detectAndCompute(image_left_gray, None)
kp_right, des_right = sift.detectAndCompute(image_right_gray, None)
# 绘制关键点
draw_left = cv2.drawKeypoints(
    image_left_gray, kp_left, None, flags=cv2.DRAW_MATCHES_FLAGS_NOT_DRAW_SINGLE_POINTS
)
draw_right = cv2.drawKeypoints(
    image_right_gray, kp_right, None, flags=cv2.DRAW_MATCHES_FLAGS_NOT_DRAW_SINGLE_POINTS
)
# 显示图片
cv2.imshow('draw_left', np.hstack((image_left, draw_left)))
cv2.imshow('draw_right', np.hstack((image_right, draw_right)))
cv2.waitKey(0)
# 保存图片
cv2.imwrite('draw_left.png', np.hstack((image_left, draw_left)))
cv2.imwrite('draw_right.png', np.hstack((image_right, draw_right)))

运行后保存图片:
请添加图片描述

在这里插入图片描述

2.利用匹配器 匹配两个描述符的相近程度,并将特征点进行连线

# 使用**cv.BFMatcher**()创建BFMatcher对象
bf = cv2.BFMatcher()
# 利用匹配器 匹配两个描述符的相近程度
# (knn 匹配可以返回k个最佳的匹配项    bf返回所有的匹配项)
matches = bf.knnMatch(des_right, des_left, k=2)
# 按照相近程度,进行排序
matches = sorted(matches, key=lambda x: x[0].distance / x[1].distance)

good = []

for m, n in matches:
    # 对欧式距离进行筛选d
    if m.distance < 0.6 * n.distance:
        good.append(m)
all_good_image = cv.drawMatches(
        img_right, key_right, img_left, key_left, good_match, None, None, None, None, flags=2
    )
    bfs.img_show("关键点之间进行连线", all_goog_image)

在这里插入图片描述

3.对图像进行拼接

if len(good) > 4:
    ptsR = np.float32(
        [kp_right[m.queryIdx].pt for m in good]).reshape(-1, 1, 2)
    ptsL = np.float32(
        [kp_left[m.trainIdx].pt for m in good]).reshape(-1, 1, 2)

    ransacReprojThreshold = 4

    Homography, status = cv2.findHomography(
        ptsR, ptsL, cv2.RANSAC, ransacReprojThreshold)

    Panorama = cv2.warpPerspective(
        image_right, Homography, (image_right.shape[1] + image_left.shape[1], image_right.shape[0])
    )

    cv2.imshow("扭曲变换后的右图", Panorama)
    cv2.imwrite('扭曲变换后的右图.png', Panorama)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    Panorama[0:image_left.shape[0], 0:image_left.shape[1]] = image_left

    cv2.namedWindow("全景图", cv2.WINDOW_AUTOSIZE)
    cv2.imshow("全景图", Panorama)
    cv2.imwrite("END.png", Panorama)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

在这里插入图片描述
在这里插入图片描述

    Panorama[0:image_left.shape[0], 0:image_left.shape[1]] = image_left
ValueError: could not broadcast input array from shape (376,498,3) into shape (374,498,3)

以上保存的原因是:出现这个问题的主要原因是因为list中array的shape不一致造成的,所以发生这个问题的时候。

解决方法:这个 时候检测一下面这两段代码有没有起作用

image_right = cv2.resize(image_right, (400, 800))
image_left = cv2.resize(image_left, (400, 800))

bug解决:
在这里插入图片描述

如果我们的扭曲变换后的图最后的图出现这样的情况的话我们需要关注一下以下代码

因为这个段代码是将左图`des_left`作为模板图,右图作为`des_right`最为去匹配的图
matches = bf.knnMatch(des_left, des_right, k=2)

但是这两段代码所反映的情况是将右图作为模板图进行拼接(也就是计算机蒙了)
 Panorama = cv2.warpPerspective(
        image_right, Homography, (image_right.shape[1] + image_left.shape[1], image_right.shape[0])
    )

Panorama[0:image_left.shape[0], 0:image_left.shape[1]] = image_left

源码:

# -*- coding: UTF-8 -*-
# @Project :opencv 
# @File    :全景拼接笔记.py
# @Author  :阿龙的代码在报错
# @IDE     :PyCharm 
# @Date    :2024/4/13 16:23
import cv2
import numpy as np

# 将读取进行灰度转化,并且输出图像,关键点和计算描述
image_left = cv2.imread("C:\\Users\\HONOR\\Desktop\\image\\pinjie_1.png")
image_right = cv2.imread("C:\\Users\\HONOR\\Desktop\\image\\pinjie_2.png")
# 将图片设置为同样的大小
image_right = cv2.resize(image_right, (400, 800))
image_left = cv2.resize(image_left, (400, 800))
# 图像灰度化
gray_left = cv2.cvtColor(image_left, cv2.COLOR_BGR2GRAY)
gray_right = cv2.cvtColor(image_right, cv2.COLOR_BGR2GRAY)

sift = cv2.SIFT_create()

kp_left, des_left = sift.detectAndCompute(image_left, None)
kp_right, des_right = sift.detectAndCompute(image_right, None)

draw_left = cv2.drawKeypoints(
    gray_left, kp_left, None, flags=cv2.DRAW_MATCHES_FLAGS_NOT_DRAW_SINGLE_POINTS)

draw_right = cv2.drawKeypoints(
    gray_right, kp_right, None, flags=cv2.DRAW_MATCHES_FLAGS_NOT_DRAW_SINGLE_POINTS)

# 显示图片
cv2.imshow('draw_left', np.hstack((image_left, draw_left)))
cv2.imshow('draw_right', np.hstack((image_right, draw_right)))
cv2.waitKey(0)
# 保存图片
cv2.imwrite('draw_left.png', np.hstack((image_left, draw_left)))
cv2.imwrite('draw_right.png', np.hstack((image_right, draw_right)))

# 使用**cv.BFMatcher**()创建BFMatcher对象
bf = cv2.BFMatcher()
# 利用匹配器 匹配两个描述符的相近成都
# (knn 匹配可以返回k个最佳的匹配项    bf返回所有的匹配项)
matches = bf.knnMatch(des_right, des_left, k=2)

# queryDescriptors:查询图像的特征描述子集 (第一个参数)
# trainDescriptors:训练图像的特征描述子集 (第二个参数)
# 按照相近程度,进行排序
matches = sorted(matches, key=lambda x: x[0].distance / x[1].distance)

good = []

for m, n in matches:
    # 对欧式距离进行筛选
    if m.distance < 0.6 * n.distance:
        good.append(m)
all_goog_image = cv2.drawMatches(
    image_right, kp_right, image_left, kp_left, good, None, None, None, None, flags=2
)
cv2.imshow("关键点之间进行连线", all_goog_image)
cv2.imwrite('all_good.png', all_goog_image)

if len(good) > 4:
    ptsR = np.float32(
        [kp_right[m.queryIdx].pt for m in good]).reshape(-1, 1, 2)
    ptsL = np.float32(
        [kp_left[m.trainIdx].pt for m in good]).reshape(-1, 1, 2)

    ransacReprojThreshold = 4

    Homography, status = cv2.findHomography(
        ptsR, ptsL, cv2.RANSAC, ransacReprojThreshold)

    Panorama = cv2.warpPerspective(
        image_right, Homography, (image_right.shape[1] + image_left.shape[1], image_right.shape[0])
    )

    cv2.imshow("扭曲变换后的右图", Panorama)
    cv2.imwrite('扭曲变换后的右图.png', Panorama)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    Panorama[0:image_left.shape[0], 0:image_left.shape[1]] = image_left

    cv2.namedWindow("全景图", cv2.WINDOW_AUTOSIZE)
    cv2.imshow("全景图", Panorama)
    cv2.imwrite("END.png", Panorama)
    cv2.waitKey(0)
    cv2.destroyAllWindows(

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

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

相关文章

001_IoT/物联网通信协议基础: HTTP、Websocket、MQTT、AMQP、COAP、LWM2M一文搞懂

001_IoT/物联网通信协议基础: HTTP、Websocket、MQTT、AMQP、COAP、LWM2M一文搞懂 文章目录 001_IoT/物联网通信协议基础: HTTP、Websocket、MQTT、AMQP、COAP、LWM2M一文搞懂创作背景通信模型ISO/OSI七层模型 和 TCP/IP四层模型网络通信数据包格式&#xff08;Ethernet II&…

【微信小程序——案例——本地生活(列表页面)】

案例——本地生活&#xff08;列表页面&#xff09; 九宫格中实现导航跳转——以汽车服务为案例&#xff08;之后可以全部实现页面跳转——现在先实现一个&#xff09; 在app.json中添加新页面 修改之前的九宫格view改为navitage 效果图&#xff1a; 动态设置标题内容—…

【5G PHY】5G无线链路监测原理简述

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 本人就职于国际知名终端厂商&#xff0c;负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作&#xff0c;目前牵头6G算力网络技术标准研究。 博客…

车载电子电器架构 —— 平行开发策略

车载电子电器架构 —— 平行开发策略 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己…

架构师系列-搜索引擎ElasticSearch(八)- 集群管理故障恢复

故障转移 集群的master节点会监控集群中的节点状态&#xff0c;如果发现有节点宕机&#xff0c;会立即将宕机节点的分片数据迁移到其它节点&#xff0c;确保数据安全&#xff0c;这个叫做故障转移。 下图中node1是主节点&#xff0c;其他两个节点是从节点 节点故障 此时node1…

【LeetCode】回溯算法类题目详解

所有题目均来自于LeetCode&#xff0c;刷题代码使用的Python3版本 回溯算法 回溯算法是一种搜索的方法&#xff0c;在二叉树总结当中&#xff0c;经常使用到递归去解决相关的问题&#xff0c;在二叉树的所有路径问题中&#xff0c;我们就使用到了回溯算法来找到所有的路径。 …

计算机网络 实验指导 实验17

实验17 配置无线网络实验 1.实验拓扑图 Table PC0 和 Table PC1 最开始可能还会连Access Point0&#xff0c;无影响后面会改 名称接口IP地址网关地址Router0fa0/0210.10.10.1fa0/1220.10.10.2Tablet PC0210.10.10.11Tablet PC1210.10.10.12Wireless互联网220.10.10.2LAN192.16…

CSS-布局

display display 属性是用于控制 布局 的最重要的 CSS 属性。display 属性规定是否/如何显示元素。 每个 HTML 元素都有一个默认的 display 值&#xff0c;具体取决于它的元素类型。大多数元素的默认 display 值为 block 或 inline。 block block&#xff1a;块级元素。块级…

STL--list双向链表

功能 将数据进行链式存储 链表&#xff08;list&#xff09;是一种物理存储单元上非连续的存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的指针链接实现的 链表的组成&#xff1a;链表由一系列结点组成 结点的组成&#xff1a;一个是存储数据元素的数据域&#xff0…

Java应用中文件上传安全性分析与安全实践

✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天开心哦&#xff01;✨✨ &#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; 目录 引言 一. 文件上传的风险 二. 使用合适的框架和库 1. Spr…

Tomcat服务器入门介及用postman工具简单接收数据 2024详解

Tomcat服务器 简介 Tomcat是一个开源的Servlet容器&#xff0c;也是一个支持Java Servlet和JSP技术的Web服务器。它由Apache软件基金会开发和维护。Tomcat的主要作用是将Java Servlet和JavaServer Pages&#xff08;JSP&#xff09;等动态网页技术部署到服务器上&#xff0c;…

Linux操作系统中关于用户管理的操作

创建新用户 useradd 【选项】 用户名 在/etc/passwd中以追加的方式在passwd的最后一行添加用户信息。 可以使用命令tail -n 1/etc/passwd查看文件的最后一行内容。 ls /home/首先/home/这是普通用户的家目录&#xff0c; 在/home/下会有一个跟用户名同名的家目录&#xf…

推荐一款基于vim的超可扩展文本编辑器neovim

一、简介 Vim是一个基于流行的Vi编辑器的文本编辑器&#xff0c;最初是在20世纪70年代发布的。Vim代表“改进的Vi”&#xff0c;它拥有广泛的用户基础和广泛的可用插件和扩展。 Neovim是Vim的一个分支&#xff0c;创建于2014年&#xff0c;旨在解决Vim的一些缺点&#xff0c;…

Node.js留言板(超详细注释)

目录结构如下 app.js // 一.引入模块 var http require(http);// 用于创建 HTTP 服务器和处理 HTTP 请求 var fs require(fs);// 用于读取和写入文件 var url require(url);// 用于解析URL// 创建留言数据对象 var msgs [{ name: 牛二, content: "我是妞儿", cr…

Hadoop+Spark大数据技术(微课版)曾国荪、曹洁版思维导图第四次作业 (第4章 HBase分布式DB)

1.简述Hbase的特点及与传统关系数据库的区别 HBase与传统关系数据库的区别 &#xff08;1&#xff09;数据类型 关系数据库具有丰富的数据类型&#xff0c;如字符串型、数值型、日期型、二进制型等。HBase只有字符串数据类型&#xff0c;数据的实际类型都是交由用户自己编写程序…

Spring+SpringMVC的知识总结

一:技术体系架构二:SpringFramework介绍三:Spring loC容器和核心概念3.1 组件和组件管理的概念3.1.1什么是组件:3.1.2:我们的期待3.1.3Spring充当组件管理角色(IOC)3.1.4 Spring优势3.2 Spring Ioc容器和容器实现3.2.1普通和复杂容器3.2.2 SpringIOC的容器介绍3.2.3 Spring IOC…

开源版中文和越南语贷款源码贷款平台下载 小额贷款系统 贷款源码运营版

后台 代理 前端均为vue源码&#xff0c;前端有中文和越南语 前端ui黄色大气&#xff0c;逻辑操作简单&#xff0c;注册可对接国际短信&#xff0c;可不对接 用户注册进去填写资料&#xff0c;后台审批&#xff0c;审批状态可自定义修改文字显示 源码免费下载地址抄笔记 (chaob…

【Vue】新手一步一步安装 vue 语言开发环境

文章目录 1、下载node.js安装包 1、下载node.js安装包 1.打开node.js的官网下载地址&#xff1a;http://nodejs.cn/download/ 选择适合自己系统的安装包&#xff1a;winds、mac 2. 配置node.js和npm环境变量 安装好之后&#xff0c;对npm安装的全局模块所在路径以及缓存所在路…

Linux网络基础 (二) ——(IP、MAC、端口号、TCPUDP协议、网络字节序)

文章目录 IP 地址基本概念源IP地址 & 目的IP地址 MAC 地址基本概念源MAC地址 & 目的MAC地址 端口号基本概念源端口号 & 目的端口号 TCP & UDP 协议基本概念TCP 与 UDP 的抉择 网络字节序大端、小端字节序 &#x1f396; 博主的CSDN主页&#xff1a;Ryan.Alask…

五、Jenkins、Docker、SpringClound持续集成

Jenkins、Docker、SpringClound持续集成 一、部署介绍1.部署图2.微服务项目结构3.项目启动顺序 二、微服务项目在Windows运行1.配置java、maven环境2.初始化数据库表/数据2.1 tensquare_gathering服务表2.2 tensquare_gathering服务表 3.启动微服务4.微服务接口测试4.1 获取用户…