opencv 实现两个图片的拼接去重功能

news2024/9/21 20:28:34

基础知识介绍

cv::Mat 是OpenCV库中用来表示图像和矩阵数据的核心类之一。它是一个多维数组,可以存储图像像素数据、矩阵数据以及其他类型的数据。以下是关于 cv::Mat 类的一些详细解释:

  1. 构造函数cv::Mat 类有多个构造函数,可以用来创建不同类型的矩阵。常用的构造函数包括:

    • cv::Mat(): 默认构造函数,创建一个空的矩阵。
    • cv::Mat(int rows, int cols, int type): 创建指定行数、列数和数据类型的矩阵。
    • cv::Mat(cv::Size size, int type): 根据指定的大小和数据类型创建矩阵。
    • cv::Mat(int rows, int cols, int type, void* data, size_t step): 使用指定的数据指针和步长创建矩阵。
  2. 成员函数cv::Mat 类提供了许多成员函数,用于对矩阵进行操作,包括:

    • rows(): 返回矩阵的行数。
    • cols(): 返回矩阵的列数。
    • size(): 返回矩阵的大小。
    • at<>(): 访问矩阵中的像素值。
    • clone(): 复制矩阵。
    • copyTo(): 将矩阵复制到另一个矩阵。
    • convertTo(): 转换矩阵的数据类型。
  3. 数据访问:可以通过 at<>() 函数或者使用 Mat::ptr 来访问矩阵中的像素值。例如,mat.at<uchar>(i, j) 可以获取矩阵中第 i 行、第 j 列的像素值。

  4. 数据类型cv::Mat 支持多种数据类型,包括整数、浮点数等。数据类型由 type() 函数返回,常见的数据类型包括 CV_8UCV_32F 等。

  5. 图像处理cv::Mat 类经常用于图像处理,可以通过 imread() 读取图像文件,通过 imwrite() 写入图像文件,还可以进行图像的剪裁、缩放、旋转等操作。

cv::Rect 是OpenCV库中用来表示矩形区域的类。它通常用于定义矩形的位置和大小,以便在图像处理中进行裁剪、绘制等操作。以下是关于 cv::Rect 类的一些详细解释:

  1. 构造函数cv::Rect 类有多个构造函数,可以用来创建不同类型的矩形。常用的构造函数包括:

    • cv::Rect(): 默认构造函数,创建一个空的矩形。
    • cv::Rect(int x, int y, int width, int height): 创建一个指定位置和大小的矩形。
    • cv::Rect(cv::Point pt1, cv::Point pt2): 根据两个点的坐标创建矩形,其中一个点表示左上角,另一个点表示右下角。
  2. 成员变量cv::Rect 类包含以下成员变量:

    • x: 矩形左上角的 x 坐标。
    • y: 矩形左上角的 y 坐标。
    • width: 矩形的宽度。
    • height: 矩形的高度。
  3. 成员函数cv::Rect 类提供了一些成员函数,用于方便地操作矩形,包括:

    • area(): 返回矩形的面积。
    • contains(): 判断一个点是否在矩形内部。
    • tl(): 返回矩形的左上角点。
    • br(): 返回矩形的右下角点。
    • size(): 返回矩形的大小。
  4. 使用cv::Rect 类通常用于定义感兴趣区域(Region of Interest,ROI),可以通过矩形来指定图像中的一个区域,然后进行裁剪、绘制等操作。

两个图片的拼接

int main()
{
    //输入两个图片
    cv::Mat image1 = cv::imread("../../picture/1.jpg");
    cv::Mat image2 = cv::imread("../../picture/2.jpg");
    //新图片的长宽
    int newWidth = image1.cols + image2.cols;
    int newHeight = std::max(image1.rows, image2.rows);
    //初始化结果图像
    cv::Mat resultImage(newHeight, newWidth, image1.type());
    //复制图像内容
    cv::Mat left(resultImage, cv::Rect(0, 0, image1.cols, image1.rows));
    image1.copyTo(left);
    cv::Mat right(resultImage, cv::Rect(image1.cols, 0, image2.cols, image2.rows));
    image2.copyTo(right);
    //保存图像
    cv::imwrite("../../picture/result.jpg", resultImage);

图片去重

int quchong()
{
    cv::Mat image1 = cv::imread("../../picture/1.jpg");
    cv::Mat image2 = cv::imread("../../picture/2.jpg");

    //夜色空间转换
    cv::Mat grayImage1, grayImage2;
    cv::cvtColor(image1, grayImage1, cv::COLOR_BGR2GRAY);
    cv::cvtColor(image2, grayImage2, cv::COLOR_BGR2GRAY);
    cv::imwrite("../../picture/BGR2GRAY.jpg", grayImage1);
    // 使用ORB特征检测器和描述符进行特征提取
    cv::Ptr<cv::ORB> orb = cv::ORB::create();
    std::vector<cv::KeyPoint> keypoints1, keypoints2;
    cv::Mat descriptors1, descriptors2;
    orb->detectAndCompute(image1, cv::noArray(), keypoints1, descriptors1);
    orb->detectAndCompute(image2, cv::noArray(), keypoints2, descriptors2);
    cv::imwrite("../../picture/descriptors1.jpg", descriptors1);
    // 使用暴力匹配器进行特征匹配
    cv::BFMatcher matcher(cv::NORM_HAMMING);
    std::vector<cv::DMatch> matches;
    matcher.match(descriptors1, descriptors2, matches);

    // 筛选匹配点
    std::vector<cv::Point2f> matchedPoints1, matchedPoints2;
    for (const cv::DMatch& match : matches) {
        matchedPoints1.push_back(keypoints1[match.queryIdx].pt);
        matchedPoints2.push_back(keypoints2[match.trainIdx].pt);
    }

    // 计算透视变换矩阵
    cv::Mat H = cv::findHomography(matchedPoints2, matchedPoints1, cv::RANSAC);
    cv::imwrite("../../picture/H.jpg", H);
    // 对第二张图像进行透视变换
    cv::Mat warpedImage2;
    cv::warpPerspective(image2, warpedImage2, H, cv::Size(image1.cols + image2.cols, image1.rows));
    cv::imwrite("../../picture/warpedImage2.jpg", warpedImage2);
    // 将两张图像拼接在一起
    cv::Mat resultImage = warpedImage2.clone();
    image1.copyTo(resultImage(cv::Rect(0, 0, image1.cols, image1.rows)));

    cv::imwrite("../../picture/result.jpg", resultImage);
    return 0;
}

实验结果

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

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

相关文章

JavaWeb(后端)

Maven Apache Maven 是一个项目管理和构建工具&#xff0c;它基于项目对象模型(POM)的概念&#xff0c;通过一小段描述信息来管理项目的构建。 Maven的作用 依赖管理&#xff1a;方便快捷的管理项目依赖的资源(jar包)&#xff0c;避免版本冲突问题。 统一项目结构&#xff…

Leetcode22括号生成(java实现)

今天分享的题目是Leetcode22括号生成&#xff0c;具体的题目描述如下&#xff1a; 本道题我们使用的解法是回溯。 解题思路&#xff1a; 我们主要是对括号出现的可能性进行一个收集。 我们以n2举例子&#xff0c;如下图 如果想要合法&#xff0c;那么一定是左括号开始&#…

golang学习笔记05——golang协程池,怎么实现协程池?

推荐学习文档 golang实战大纲golang优秀开发常用开源库汇总golang学习笔记01——基本数据类型golang学习笔记02——gin框架及基本原理golang学习笔记03——gin框架的核心数据结构golang学习笔记04——如何真正写好Golang代码&#xff1f; 协程池是一种用于高效处理任务的机制&…

Claude的小白入门指南

要想快速上手Claude AI&#xff0c;其实并没有那么复杂。作为新一代的AI助手&#xff0c;Claude致力于为用户提供高效、无害、透明的交互体验。这篇入门指南将从Claude AI的特点、主要功能和如何实际操作等几个方面为大家做一个详细的介绍。 Claude AI是什么&#xff1f; Claud…

ssh之登录服务器后,自动进入目录(四十七)

简介&#xff1a; CSDN博客专家、《Android系统多媒体进阶实战》一书作者 新书发布&#xff1a;《Android系统多媒体进阶实战》&#x1f680; 优质专栏&#xff1a; Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a; 多媒体系统工程师系列【…

0成本实现.NET Web API 8.0项目内网映射

1.背景 最近在学习CICD&#xff0c;里面会有用到内网映射的使用场景。为了加深对内网映射实操的记忆。我实操了下基于.Net 8.0的内网映射&#xff0c;并支持互联网访问。本文主要介绍了在win11下安装路由侠&#xff0c;并将.net 8.0发布到win11&#xff0c;项目运行、路由侠配…

【MiniMax】中国文生视频模型再添一员大将!

千呼万唤始出来&#xff01; 一直以低调示人的 MiniMax 终于举办了他们从成立以来的第一次公开伙伴日活动。 本次伙伴日上&#xff0c;MiniMax发布了 视频模型abab-video-1、音乐模型abab-music-1&#xff0c;更新 语音模型abab-speech-1。此外&#xff0c;MiniMax将在未来数周…

Windows10彻底关闭自带的防病毒功能

第1步:右下角,点开“windows安全中心” 第2步:切换到“病毒和威胁防护”,打开“管理设置” 第3步:将“实时防护”、“云提供的防护”、“自动提交样本”和“篡改防护”四个选项开关关闭。 第4步:按下win键+R键->打开“运行”窗口->输入命令“gpedit.msc”->“确…

2024国赛数学建模-模拟火算法(MATLAB 实现)

模拟退火算法 1.1 算法原理 模拟退火算法的基本思想是从一给定解开始 ,从邻域 中随机产生另一个解 ,接受 Metropolis准则允许目标函数在 有限范围内变坏 ,它由一控制参数 t决定 ,其作用类似于物 理过程中的温度 T,对于控制参数的每一取值 ,算法持续进 行“产生 —判断 —接受…

vue transition组件

可能不生效的几个注意点 选择器的优先级谨慎合并样式 显示三阶段和隐藏三阶段的class名 1、vue2中显示的初始阶段类名是&#xff1a;v-enter&#xff1b;隐藏的初始阶段类名是&#xff1a;v-leave2、v-enter-active、v-leave-active这两个 class 可以被用来定义动画的持续时间…

C# 删除Word文档中的段落

在编辑Word文档时&#xff0c;我们有时需要调整段落的布局、删除不必要的段落以优化文档的结构和阅读体验。本文将通过以下3个简单示例演示如何使用免费.NET库删除Word文档中的段落 。 目录 C# 删除Word中的指定段落 C# 删除Word中的所有段落 C# 删除Word中的空白段落 免费…

【运维监控】influxdb 2.0+telegraf 监控tomcat 8.5运行情况(2)

关于java应用的监控本系列有文章如下&#xff1a; 【运维监控】influxdb 2.0telegraf 监控tomcat 8.5运行情况 【运维监控】influxdb 2.0grafana 监控java 虚拟机以及方法耗时情况 【运维监控】Prometheusgrafana监控tomcat运行情况 【运维监控】Prometheusgrafana监控spring b…

vllm源码解析(三):块管理(BlockManager)

六 块管理器 6.1 块管理方法在调度系统中的应用 在第二篇文章对调度系统的分析中&#xff0c;我们可以看到调度系统中普遍都使用了块管理方法&#xff1a; _schedule_prefills ... # 比较当前seq需要的物理块,gpu可用物理块之间的数量关系. 决定是否能给当前seq_group分配物…

828华为云征文|部署内容管理系统 Joomla

828华为云征文&#xff5c;部署内容管理系统 Joomla 一、Flexus云服务器X实例介绍1.1 云服务器介绍1.2 应用场景1.3 核心竞争力 二、Flexus云服务器X实例配置2.1 重置密码2.2 服务器连接2.3 安全组配置 三、部署 Joomla3.1 Joomla 介绍3.2 Docker 环境搭建3.3 Joomla 部署3.4 J…

阿里中间件——diamond

一、前言 最近工作不忙闲来无事&#xff0c;仔细分析了公司整个项目架构&#xff0c;发现用到了很多阿里巴巴集团开源的框架&#xff0c;今天要介绍的是中间件diamond. 二、diamond学习笔记 1、diamond简介 diamond是一个管理持久配置&#xff08;持久配置是指配置数据会持久化…

倒计时7天!CCS2024大模型安全与产业应用创新研讨活动诚邀你来

当下&#xff0c;“人工智能”已成为催生新质生产力的重要引擎&#xff0c;大模型在加速产业升级和经济增长的同时&#xff0c;也为网络安全带来了全新的机遇与挑战。「大模型安全与产业应用创新研讨活动」由百度安全、成都无糖信息联合承办&#xff0c;特邀云安全联盟CSA大中华…

Windows用户取消共享文件夹密码方法(Method for Windows Users to Cancel Shared Folder Password)

Windows用户取消访问共享文件夹密码方法 &#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您…

IP学习——oneday

1.什么是网络&#xff1f;为什么需要网络&#xff1f; 空间&#xff0c;时间&#xff1b;传统的邮件传输要考虑到距离&#xff0c;网络解决了空间距离&#xff08;太远&#xff09;、解决了时间问题&#xff08;旧音乐等&#xff09; 云:面向客户的虚拟化服务 运营商公司主营…

【运维监控】influxdb 2.0+telegraf 监控tomcat 8.5运行情况(1)

关于java应用的监控本系列有文章如下&#xff1a; 【运维监控】influxdb 2.0telegraf 监控tomcat 8.5运行情况 【运维监控】influxdb 2.0grafana 监控java 虚拟机以及方法耗时情况 【运维监控】Prometheusgrafana监控tomcat运行情况 【运维监控】Prometheusgrafana监控spring b…

02 Flask-快速上手

创建项目文件 从电脑选择一个盘符(来存放之后学习的项目文件) 这里选择以电脑C盘的桌面来做演示 在选择的盘符里面创建一个文件夹(来保存之后的学习文件) 使用 poetry 创建一个初始配置项(pyproject.toml) 详情参考 poetry init创建虚拟环境 poetry env use python激活虚拟…