OpenCV之sift图像匹配

OpenCV提供的视觉处理算法非常丰富,并且她部分以C语言编写,加上其开源的特性,处理得当,不需要添加新的外部支持也可以完整的编译连接生成执行程序。

SIFT算法的特点有:

1. SIFT特征是图像的局部特征,其对旋转、尺度缩放、亮度变化保持不变性,对视角变化、仿射变换、噪声也保持一定程度的稳定性;

2. 独特性(Distinctiveness)好,信息量丰富,适用于在海量特征数据库中进行快速、准确的匹配;

3. 多量性,即使少数的几个物体也可以产生大量的SIFT特征向量;

4. 高速性,经优化的SIFT匹配算法甚至可以达到实时的要求;

5. 可扩展性,可以很方便的与其他形式的特征向量进行联合。

       BF算法:

       即暴风(Brute Force)算法,是普通的模式匹配算法,BF算法的思想就是将目标串S的第一个字符与模式串T的第一个字符进行匹配,若相等,则继续比较S的第二个字符和 T的第二个字符;若不相等,则比较S的第二个字符和T的第一个字符,依次比较下去,直到得出最后的匹配结果。BF算法是一种蛮力算法。

#include <opencv2/core/core.hpp>  
#include <opencv2/highgui/highgui.hpp>  
#include <opencv2/nonfree/features2d.hpp> 
#include <iostream>  
using namespace cv;  
using namespace std;  
   
int main(int argc, const char *argv[]){  
    Mat I1 = imread("添加图片地址", 0);// 载入灰度图像 ,0表示灰度图像
    Mat I2 = imread("添加图片地址", 0);  
  
    SiftFeatureDetector detector;     //sift特征提取
    vector<KeyPoint> keypoints1, keypoints2;  // 定义关键点
    detector.detect(car1, keypoints1);     //检测关键点
    detector.detect(car2, keypoints2);  
    cout << "# keypoints of I1 :" << keypoints1.size() << endl;    //输出关键点的数量
    cout << "# keypoints of I2 :" << keypoints2.size() << endl;  
     
    Mat descriptors1,descriptors2;                                   //定义描述符
    Ptr<DescriptorExtractor> extractor = DescriptorExtractor::create("SIFT");  //描述符提取
    extractor->compute(I1,keypoints1,descriptors1);  
    extractor->compute(I2,keypoints2,descriptors2);     //提取关键点的和描述关键点
      
    BFMatcher bfmatcher(NORM_L2, true);                       // 暴风匹配
    vector<DMatch> matches;  
    bfmatcher.match(descriptors1, descriptors2, matches);  
    cout << "# matches : " << matches.size() << endl;  
  
  
    // 显示图像  
    Mat output;  
    drawMatches(I1, keypoints1, I2, keypoints2, matches, output);   //对两幅图上的关键点进行连线
    imshow("匹配结果",output);  
    imshow("载入原始图像地址",I1);
    imshow("载入原始图像地址",I2);
    waitKey(0);  
    return 0;  
}  

实验结果:


参考:

关键点描述子匹配

Common Interfaces of Descriptor Matchers

SIFT原理与源码分析


<think>首先,用户的问题是关于暴力匹配算法的完整代码示例。用户说:“我想查找暴力匹配算法的完整示例 请问暴力匹配算法完整代码示例”。所以,我需要提供暴力匹配算法的完整代码示例。 从系统级指令中,我需要使用中文回答,并确保结构清晰。回答中要包括代码示例,并自然地添加引用标识。引用来自提供的引用内容。 回顾引用内容: - 引用[1]:关于字符串匹配算法的暴力做法(朴素算法),介绍了基本思路和Java实现。 - 引用[2]:描述了暴力匹配的实现方式,包括时间复杂度分析。 - 引用[3]:Java实现暴力匹配算法的详细解释。 - 引用[4]:C语言实现的BF(Brute-Force)暴力匹配算法示例。 - 引用[5]:KMP算法的实现,但用户问的是暴力匹配,所以我应该忽略这个,除非相关。 用户指定了暴力匹配算法,所以我专注于引用[1]、[2]、[3]和[4],这些直接相关。 我需要生成完整代码示例。引用[4]提供了C语言的完整代码,引用[3]提供了Java实现。我应该选择一种语言,或者提供多种?用户没有指定语言,所以我应该参考引用中的内容。引用[3]和[4]分别有Java和C,我可以提供两者,但为了简洁,或许选择一个代表性的。 用户说“完整代码示例”,所以我应该提供完整的、可运行的代码。 此外,系统指令要求生成相关问题。在回答末尾,我需要添加相关问题。 回答结构: 1. **介绍暴力匹配算法**:简要解释它是什么,基于引用。 2. **提供代码示例**:选择一种语言,比如Java或C,从引用中提取。引用[4]有C代码,引用[3]有Java解释。我可以使用引用[4]的C代码,因为它更完整。 3. **解释代码**:帮助用户理解代码,逐步解释。 4. **添加引用**:在相关段落末尾添加引用标识,如[^1]。 5. **生成相关问题**:在最后添加几个相关问题。 现在,提取代码: - 从引用[4]:有C语言的BF算法实现。代码包括函数定义、主函数和示例。 代码: ```c #include <stdio.h> #include <string.h> // BF算法实现 int BF(const char* text, const char* pattern) { int textLen = strlen(text); int patternLen = strlen(pattern); for (int i = 0; i <= textLen - patternLen; i++) { int j; for (j = 0; j < patternLen; j++) { if (text[i + j] != pattern[j]) { break; } } if (j == patternLen) { return i; } } return -1; } int main() { const char* text = "hello world, welcome to the world of programming!"; const char* pattern = "world"; int index = BF(text, pattern); if (index != -1) { printf("Pattern found at index: %d\n", index); } else { printf("Pattern not found.\n"); } return 0; } ``` - 引用[3]有Java实现的描述,但没有完整代码。我可以基于描述写一个Java版本,但最好使用现有的。 为了完整性,我可以提供Java版本,但引用[4]的C代码是完整的,所以我用那个。 在回答中,我需要用中文解释。 步骤: 1. **开头介绍**:解释暴力匹配算法是什么。 2. **提供代码**:粘贴C代码,并解释关键部分。 3. **添加引用**:在解释时引用来源。 4. **生成相关问题**:在末尾添加。 相关问题示例: - 暴力匹配算法的时间复杂度是什么? - 如何优化暴力匹配算法? - 暴力匹配算法在哪些场景下适用? 基于引用[2],时间复杂度是O(n*m)最坏情况。 现在,写回答。</think>### 暴力匹配算法完整代码示例 暴力匹配算法(也称为朴素字符串匹配算法或Brute-Force算法)是一种基础的字符串匹配方法,它通过逐个字符比较来查找子串在主串中的位置。算法的核心思想是:从主串的第一个字符开始,依次与模式串的每个字符进行比对;如果匹配失败,则主串指针后移一位,重新开始匹配。这种方法简单直观,但效率较低,最坏时间复杂度为 $O(n \times m)$,其中 $n$ 是主串长度,$m$ 是模式串长度[^2]。下面我将提供一个完整的、可运行的代码示例,并逐步解释其实现细节。 #### C语言实现暴力匹配算法 以下是暴力匹配算法的完整C语言实现示例。代码包括算法函数定义、主函数测试逻辑和详细注释。此实现基于BF(Brute-Force)算法的标思路,直接从主串和模式串的字符一一比对开始[^4]。 ```c #include <stdio.h> #include <string.h> // BF算法实现函数 // 参数: text是主字符串, pattern是模式串(子串) // 返回值: 如果找到模式串,返回其在主串中的起始索引(从0开始);否则返回-1 int BF(const char* text, const char* pattern) { int textLen = strlen(text); // 获取主串长度 int patternLen = strlen(pattern); // 获取模式串长度 // 遍历主串,i是主串的起始索引 for (int i = 0; i <= textLen - patternLen; i++) { int j; // j用于遍历模式串 // 内层循环:逐个比较主串和模式串的字符 for (j = 0; j < patternLen; j++) { // 如果字符不匹配,跳出内层循环 if (text[i + j] != pattern[j]) { break; } } // 如果j达到模式串长度,说明匹配成功 if (j == patternLen) { return i; // 返回匹配的起始索引 } } return -1; // 未找到匹配 } // 主函数:测试BF算法 int main() { const char* text = "hello world, welcome to the world of programming!"; // 主串示例 const char* pattern = "world"; // 模式串示例 int index = BF(text, pattern); // 调用匹配函数 // 输出匹配结果 if (index != -1) { printf("模式串在主串中的起始位置: %d\n", index); } else { printf("未找到匹配的模式串。\n"); } return 0; } ``` #### 代码解释 1. **算法函数 `BF`**: - 外层循环 `for (int i = 0; i <= textLen - patternLen; i++)` 控制主串的起始位置,确保不会越界。 - 内层循环 `for (j = 0; j < patternLen; j++)` 逐个比较主串从位置 `i` 开始的字符与模式串的字符。 - 如果字符不匹配 (`text[i + j] != pattern[j]`),立即跳出内层循环,主串指针后移一位(通过 `i++`)。 - 如果内层循环完整执行(`j == patternLen`),表示匹配成功,返回当前起始索引 `i`。 - 如果遍历完主串仍未匹配,返回 `-1`。 2. **主函数测试**: - 示例中,主串是 `"hello world, welcome to the world of programming!"`,模式串是 `"world"`。 - 调用 `BF` 函数后,输出匹配结果。运行此代码会打印:`模式串在主串中的起始位置: 6`(因为 `"world"` 第一次出现的位置是索引6)。 这个实现直观展示了暴力匹配的核心过程:像“滑块”一样在主串上滑动,直到找到完全匹配的子串[^2]。算法的优点是简单易懂,适合教学或小规模数据;缺点是效率低,最坏情况下需比较 $n \times m$ 次(例如主串为 `"aaaaaaaab"`,模式串为 `"aab"` 时)[^2]。 #### Java语言实现补充 如果您需要Java版本,基于引用[3]的描述,以下是简洁实现: ```java public class BruteForceMatch { public static int bruteForce(String text, String pattern) { int n = text.length(); int m = pattern.length(); for (int i = 0; i <= n - m; i++) { int j; for (j = 0; j < m; j++) { if (text.charAt(i + j) != pattern.charAt(j)) { break; } } if (j == m) { return i; // 匹配成功 } } return -1; // 未匹配 } public static void main(String[] args) { String text = "hello world"; String pattern = "world"; int index = bruteForce(text, pattern); if (index != -1) { System.out.println("匹配位置: " + index); } else { System.out.println("未找到匹配"); } } } ``` Java实现逻辑与C版本一致,仅语法差异:使用 `charAt` 方法访问字符,并集成到类中[^3]。 ### 相关问题 1. 暴力匹配算法的最坏时间复杂度是什么?在哪些情况下会出现最坏性能?[^2] 2. 如何优化暴力匹配算法以提高效率?例如,能否结合其他算法(如KMP)?[^5] 3. 暴力匹配算法在实际应用中有哪些常见场景?例如,在文本编辑器或简单数据搜索中的作用?[^1] [^1]: 字符串匹配算法之暴力做法(朴素算法)。 [^2]: 暴力实现模式匹配的方式:从S的第一个字符开始,逐个匹配P的每个字符。 [^3]: java实现暴力匹配算法详解。 [^4]: 数据结构串的模式匹配算法--BF暴力匹配。 [^5]: 深入解析 KMP 算法 —— 高效的字符串匹配利器。
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值