机器视觉基础实验-Panorama Stitching

news2024/11/17 1:53:19

文章目录

  • 1、实验内容
  • 2、实验设计(略)
  • 3、实验环境及实验数据集
  • 四、实验过程及结果
    • 4.1 Harris角点检测器寻找关键点
    • 4.2 构建描述算子来描述图中的每个关键点,比较两幅图像的两组描述子,并进行匹配。
    • 4.3 根据一组匹配关键点,使用最小二乘法进行仿射变换矩阵的计算
    • 4.4 使用RANSAC计算一个更加稳定的仿射变换的矩阵,然后将第二幅图变换过来并覆盖在第一幅图上,形成一个全景
    • 4.5 实现不同的描述子HOG,得到不同的拼接结果

1、实验内容

实验题目:Implement Panorama Stitching with Harris corner detector, RANSAC and HOG descriptor.
实验步骤:

  • 1.使用Harris焦点检测器寻找关键点。
  • 2.构建描述算子来描述图中的每个关键点,比较两幅图像的两组描述子,并进行匹配。
  • 3.根据一组匹配关键点,使用最小二乘法进行仿射变换矩阵的计算。
  • 4.使用RANSAC计算一个更加稳定的仿射变换的矩阵,然后将第二幅图变换过来并覆盖在第一幅图上,形成一个全景。
  • 5.实现不同的描述子,并得到不同的拼接结果。

2、实验设计(略)

3、实验环境及实验数据集

实验环境:

  • Windows10的操作系统、anaconda3、python3.6、jupyter notebook。

数据集:

  • 任务给出的原图片以及处理结果后的图片,如image1.jpg、image2.jpg、solution_harris.png等等。

四、实验过程及结果

4.1 Harris角点检测器寻找关键点

结果展示:
在这里插入图片描述
实现代码:

1.def harris_corners(img, window_size=3, k=0.04):  
2. """ 
3. Compute Harris corner response map. Follow the math equation 
4. R=Det(M)-k(Trace(M)^2). 
5. 
6. Hint: 
7.     You may use the function scipy.ndimage.filters.convolve, 
8.     which is already imported above. 
9. 
10. Args: 
11.     img: Grayscale image of shape (H, W) 
12.     window_size: size of the window function 
13.     k: sensitivity parameter 
14. 
15. Returns: 
16.     response: Harris response image of shape (H, W) 
17. """  
18.  
19. H, W = img.shape  
20. window = np.ones((window_size, window_size))  
21.  
22. response = np.zeros((H, W))  
23.  
24. dx = filters.sobel_v(img)  
25. dy = filters.sobel_h(img)  
26.  
27. ### YOUR CODE HERE  
28. Ix2 = np.multiply(dx,dx)  
29. Iy2 = np.multiply(dy,dy)  
30. IxIy = np.multiply(dx,dy)  
31.   
32. #高斯加权  
33. A = convolve(Ix2,window)  
34. B = convolve(Iy2,window)  
35. C = convolve(IxIy,window)  
36.  
37. detM = np.multiply(A, B) - np.multiply(C, C)  
38. traceM = A + B  
39.  
40. response = detM - k * np.square(traceM)  
41. ### END YOUR CODE  
42.  
 return response

4.2 构建描述算子来描述图中的每个关键点,比较两幅图像的两组描述子,并进行匹配。

结果展示:
在这里插入图片描述
在这里插入图片描述
实现代码:
构建描述算子

1.def simple_descriptor(patch):  
2. """ 
3. Describe the patch by normalizing the image values into a standard 
4. normal distribution (having mean of 0 and standard deviation of 1) 
5. and then flattening into a 1D array. 
6. 
7. The normalization will make the descriptor more robust to change 
8. in lighting condition. 
9. 
10. Hint: 
11.     If a denominator is zero, divide by 1 instead. 
12. 
13. Args: 
14.     patch: grayscale image patch of shape (H, W) 
15. 
16. Returns: 
17.     feature: 1D array of shape (H * W) 
18. """  
19. feature = []  
20. ### YOUR CODE HERE  
21. mean = np.mean(patch)  
22. sigma = np.std(patch)  
23. if sigma == 0.0:  
24.     sigma = 1  
25. #均值0,标准差为1  
26. normalized = (patch - mean) / sigma  
27. #生成一维特征向量  
28. feature = normalized.flatten()  
29. ### END YOUR CODE  
30. return feature  

根据描述子进行匹配

1.#注意,这里引入了heapq堆排列模块算法  
2.import heapq  
3.def match_descriptors(desc1, desc2, threshold=0.5):  
4.    """ 
5.    Match the feature descriptors by finding distances between them. A match is formed 
6.    when the distance to the closest vector is much smaller than the distance to the 
7.    second-closest, that is, the ratio of the distances should be smaller 
8.    than the threshold. Return the matches as pairs of vector indices. 
9. 
10.    Hint: 
11.        The Numpy functions np.sort, np.argmin, np.asarray might be useful 
12. 
13.    Args: 
14.        desc1: an array of shape (M, P) holding descriptors of size P about M keypoints 
15.        desc2: an array of shape (N, P) holding descriptors of size P about N keypoints 
16. 
17.    Returns: 
18.        matches: an array of shape (Q, 2) where each row holds the indices of one pair 
19.        of matching descriptors 
20.    """  
21.    matches = []  
22.  
23.    N = desc1.shape[0]  
24.    dists = cdist(desc1, desc2)  
25.  
26.    ### YOUR CODE HERE  
27.    for i in range(N):  
28.        #找到最近的两个值  
29.        min2 = heapq.nsmallest(2, dists[i,:])  
30.        #保证最小的和第二小的有一定的距离  
31.        if min2[0] / min2[1] < threshold:  
32.            matches.append([i, np.argmin(dists[i,:])])  
33.    matches = np.asarray(matches)  
34.    ### END YOUR CODE  
35.  
36.    return matches

4.3 根据一组匹配关键点,使用最小二乘法进行仿射变换矩阵的计算

实验结果:
在这里插入图片描述

在这里插入图片描述

实验代码:

1.def fit_affine_matrix(p1, p2):  
2. """ Fit affine matrix such that p2 * H = p1 
3. 
4. Hint: 
5.     You can use np.linalg.lstsq function to solve the problem. 
6. 
7. Args: 
8.     p1: an array of shape (M, P) 
9.     p2: an array of shape (M, P) 
10. 
11. Return: 
12.     H: a matrix of shape (P, P) that transform p2 to p1. 
13. """  
14.  
15. assert (p1.shape[0] == p2.shape[0]),\  
16.     'Different number of points in p1 and p2'  
17. p1 = pad(p1)  
18. p2 = pad(p2)  
19.  
20. ### YOUR CODE HERE  
21. #仿射变换矩阵  
22. H, residuals, rank, s = np.linalg.lstsq(p2, p1, rcond=None)  
23. ### END YOUR CODE  
24.  
25. # Sometimes numerical issues cause least-squares to produce the last  
26. # column which is not exactly [0, 0, 1]  
27. H[:,2] = np.array([0, 0, 1])  
28. return H  

4.4 使用RANSAC计算一个更加稳定的仿射变换的矩阵,然后将第二幅图变换过来并覆盖在第一幅图上,形成一个全景

实验结果:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

实验代码:

1.def ransac(keypoints1, keypoints2, matches, n_iters=200, threshold=20):  
2. """ 
3. Use RANSAC to find a robust affine transformation 
4. 
5.     1. Select random set of matches 
6.     2. Compute affine transformation matrix 
7.     3. Compute inliers 
8.     4. Keep the largest set of inliers 
9.     5. Re-compute least-squares estimate on all of the inliers 
10. 
11. Args: 
12.     keypoints1: M1 x 2 matrix, each row is a point 
13.     keypoints2: M2 x 2 matrix, each row is a point 
14.     matches: N x 2 matrix, each row represents a match 
15.         [index of keypoint1, index of keypoint 2] 
16.     n_iters: the number of iterations RANSAC will run 
17.     threshold: the number of threshold to find inliers 
18. 
19. Returns: 
20.     H: a robust estimation of affine transformation from keypoints2 to 
21.     keypoints 1 
22. """  
23. # Copy matches array, to avoid overwriting it  
24. orig_matches = matches.copy()  
25. matches = matches.copy()  
26.  
27. N = matches.shape[0]  
28. print(N)  
29. n_samples = int(N * 0.2)  
30.  
31. matched1 = pad(keypoints1[matches[:,0]])  
32. matched2 = pad(keypoints2[matches[:,1]])  
33.  
34. max_inliers = np.zeros(N)  
35. n_inliers = 0  
36.  
37. # RANSAC iteration start  
38. ### YOUR CODE HERE  
39. for i in range(n_iters):  
40.     inliersArr = np.zeros(N)  
41.     idx = np.random.choice(N, n_samples, replace=False)  
42.     p1 = matched1[idx, :]  
43.     p2 = matched2[idx, :]  
44.  
45.     H, residuals, rank, s = np.linalg.lstsq(p2, p1, rcond=None)  
46.     H[:, 2] = np.array([0, 0, 1])  
47.  
48.     output = np.dot(matched2, H)  
49.     inliersArr = np.linalg.norm(output-matched1, axis=1)**2 < threshold  
50.     inliersCount = np.sum(inliersArr)  
51.  
52.     if inliersCount > n_inliers:  
53.         max_inliers = inliersArr.copy() #这里需要注意深拷贝和浅拷贝  
54.         n_inliers = inliersCount  
55.  
56. # 迭代完成,拿最大数目的匹配点对进行估计变换矩阵  
57. H, residuals, rank, s = np.linalg.lstsq(matched2[max_inliers], matched1[max_inliers], rcond=None)  
58. H[:, 2] = np.array([0, 0, 1])  
59. ### END YOUR CODE  
60. print(H)  
61. return H, orig_matches[max_inliers]

4.5 实现不同的描述子HOG,得到不同的拼接结果

实验结果:

在这里插入图片描述

在这里插入图片描述
实验代码:

1.def hog_descriptor(patch, pixels_per_cell=(8,8)):  
2. """ 
3. Generating hog descriptor by the following steps: 
4. 
5. 1. Compute the gradient image in x and y directions (already done for you) 
6. 2. Compute gradient histograms for each cell 
7. 3. Flatten block of histograms into a 1D feature vector 
8.     Here, we treat the entire patch of histograms as our block 
9. 4. Normalize flattened block 
10.     Normalization makes the descriptor more robust to lighting variations 
11. 
12. Args: 
13.     patch: grayscale image patch of shape (H, W) 
14.     pixels_per_cell: size of a cell with shape (M, N) 
15. 
16. Returns: 
17.     block: 1D patch descriptor array of shape ((H*W*n_bins)/(M*N)) 
18. """  
19. assert (patch.shape[0] % pixels_per_cell[0] == 0),\  
20.             'Heights of patch and cell do not match'  
21. assert (patch.shape[1] % pixels_per_cell[1] == 0),\  
22.             'Widths of patch and cell do not match'  
23.  
24. n_bins = 9  
25. degrees_per_bin = 180 // n_bins  
26.  
27. Gx = filters.sobel_v(patch)  
28. Gy = filters.sobel_h(patch)  
29.  
30. # Unsigned gradients  
31. G = np.sqrt(Gx**2 + Gy**2)  
32. theta = (np.arctan2(Gy, Gx) * 180 / np.pi) % 180  
33.  
34. # Group entries of G and theta into cells of shape pixels_per_cell, (M, N)  
35. #   G_cells.shape = theta_cells.shape = (H//M, W//N)  
36. #   G_cells[0, 0].shape = theta_cells[0, 0].shape = (M, N)  
37. G_cells = view_as_blocks(G, block_shape=pixels_per_cell)  
38. theta_cells = view_as_blocks(theta, block_shape=pixels_per_cell)  
39. rows = G_cells.shape[0]  
40. cols = G_cells.shape[1]  
41.  
42. # For each cell, keep track of gradient histrogram of size n_bins  
43. cells = np.zeros((rows, cols, n_bins))  
44.  
45. # Compute histogram per cell  
46. ### YOUR CODE HERE  
47. # 首先需要遍历Cell  
48. for row in range(rows):  
49.     for col in range(cols):  
50.         # 遍历cell中的像素  
51.         for y in range(pixels_per_cell[0]):  
52.             for x in range(pixels_per_cell[1]):  
53.                 # 计算该像素的梯度方向(在n_bins个方向中属于第几个区间)  
54.                 angle = theta_cells[row,col,y,x]  
55.                 order = int(angle) // degrees_per_bin  
56.                 if order == 9:  
57.                     order = 8  
58.                 # 统计该cell中每个方向区间内的强度  
59.                 # 累加强度也可以  
60.                 cells[row,col,order] += G_cells[row,col,y,x]  
61.  
62. # 最后做归一化处理,直方图归一化  
63. cells = (cells - cells.mean()) / (cells.std())  
64. block = cells.reshape(-1) # 一维  
65. ### YOUR CODE HERE  
66.  
67. return block  

完整实验见下载连接:
https://download.csdn.net/download/qq_37534947/88222832

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

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

相关文章

Nginx的安装及负载均衡搭建

一.Nginx的安装 1&#xff09;准备安装环境 yum install -y make gcc gcc-c pcre-devel pcre zlib zlib-devel openssl openssl-develPERE PCRE(Perl Compatible Regular Expressions)是一个Perl库&#xff0c;包括 perl 兼容的正则表达式库。 nginx的http模块使用pcre来解…

每天一练:SpringBoot连接mq

目录 每天一练:Springboot连接rabbitmq 每天一练:Springboot连接rabbitmq 目录一、部署Rabbitmq&#xff1f;二、增加maven依赖三、连接RabbitMq四、发布和订阅消息总结 一、部署Rabbitmq&#xff1f; 这里rabbitmq采用docker安装部署。 拉取docker镜像 [root192 ~]# docker…

349. 两个数组的交集 题解

题目描述&#xff1a;349. 两个数组的交集 - 力扣&#xff08;LeetCode&#xff09; 给定两个数组 nums1 和 nums2 &#xff0c;返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。 方法一&#xff1a; 解题思路&#xff1a; 我们可以…

《零基础7天入门Arduino物联网-04》电路基础知识上

配套视频课程&#xff1a;《零基础学Arduino物联网&#xff0c;入门到进阶》 配套课件资料获取&#xff1a;微联实验室 配套学习套件购买&#xff1a;淘宝搜索店铺【微联实验室】 直流电与交流电 直流电&#xff08;DC&#xff09; 是指电流的方向始终保持不变的电流。这意味着…

Hyperledger Fabric的使用及开发

Hyperledger Fabric是Linux基金会发起的一种跨行业的区块链技术&#xff0c;目前在多家大型公司有着应用&#xff0c;这里就不多做HF本身的介绍了&#xff0c;有兴趣可关注其官网。 1. 准备工作&#xff1a; 开始前需要一定的准备工作&#xff0c;安装各类中间件&#xff1a;…

JVM——HotSpot的算法细节实现

一、根节点枚举 固定可作为GC Roots的节点主要在全局性的引用&#xff08;如常量或类静态属性&#xff09;与执行上下文&#xff08;如栈帧中的本地变量表&#xff09;中&#xff0c;尽管目标明确&#xff0c;但查找要做到高效很难。现在java应用越来越庞大&#xff0c;光方法区…

啥是虚拟机

虚拟机这个概念第一次听到还是在我大二学计算机网络做实验的时候听说过&#xff0c;第二次算比较熟练地使用应该是在大三下学期的大数据课程&#xff0c;做实验的时候也算是学到了许多Linux的命令。但到底什么是虚拟机&#xff0c;我还是搞不清楚的&#xff0c;所以&#xff0c…

【八股】2023秋招八股复习笔记1(CSBase+部分WXG题)

文章目录 MYSQL & redis网络 & 系统安全 & C招聘要求&#xff08;x3&#xff09;部分面经和题目&#xff08;WXG-后端&#xff09;&#xff08;x5&#xff09; MYSQL & redis redis&#xff1a;memcached/mysql&#xff0c;线程模型&#xff08;6.0多线程&…

css实现div内文字自动滚动

网上找了好久&#xff0c;终于找到了个能实现的&#xff0c;把它整理一下。 需求&#xff1a;表格内字体过长实现自动滚动 实现思路如下&#xff1a; html&#xff1a; <div class"item-column" style"background: rgb(12, 87, 154); width: 18%; height: 6…

Msvcr120.dll文件缺失怎么办.msvcr120.dll错误的解决方法

在使用某些软件时你是否有遇到过Msvcr120.dll文件缺失&#xff0c;msvcr120.dll是 Microsoft Visual C Redistributable 中的一个重要文件&#xff0c;所以它的缺失会导致应用程序无法正常使用或崩溃。那么出现这种情况应该怎么办呢&#xff1f;以下教大家几种解决方法。 一.导…

线性代数(四) 特征值相似矩阵

前言 前面主要讲述的是方程组和矩阵的关系&#xff0c;现在了解下矩阵和矩阵的关系 方阵的特征值与特征向量 假设A为n阶方阵&#xff0c;对于一个数 λ \lambda λ 若存在&#xff1a;非零列向量 α \alpha α&#xff0c;使得&#xff1a; A α ⃗ λ α ⃗ A\vec{\alp…

轮腿机器人的PID控制

1 PID介绍 PID&#xff08;Proportional Integral Derivative&#xff09;控制系统。其实质是根据输入的偏差值&#xff0c;按比例、积分、微分的函数关系进行运算&#xff0c;运算结果用以输出进行控制。它是在长期的工程实践中总结出来的一套控制方法&#xff0c;实际运行经…

在CentOS 7上使用kubeadm部署Kubernetes集群

如有错误&#xff0c;敬请谅解&#xff01; 此文章仅为本人学习笔记&#xff0c;仅供参考&#xff0c;如有冒犯&#xff0c;请联系作者删除&#xff01;&#xff01; 前言&#xff1a; Kubernetes是一个开源的容器编排平台&#xff0c;用于管理和自动化部署容器化的应用程序。…

C#8.0本质论第三章--更多数据类型

C#8.0本质论第三章–更多数据类型 3.1类型的划分 一个类型要么是值类型&#xff0c;要么是引用类型。区别在于拷贝方式&#xff1a;值类型数据总是拷贝值&#xff1b;引用类型的数据总是拷贝引用。 3.1.1值类型 3.1.2引用类型 引用类型的变量存储对数据存储位置的引用。 3.…

Datawhale Django入门组队学习Task02

Task02 首先启动虚拟环境&#xff08;复习一下之前的&#xff09; 先退出conda的&#xff0c; conda deactivate然后cd到我的venv下面 &#xff0c;然后cd 到 scripts&#xff0c;再 activate &#xff08;powershell里面&#xff09; 创建admin管理员 首先cd到项目路径下&a…

笨办法学python3进阶篇pdf,笨方法学 python3怎么样

本篇文章给大家谈谈《“笨办法”学python(第3版)》&#xff0c;以及笨办法学python3进阶篇pdf下载&#xff0c;希望对各位有所帮助&#xff0c;不要忘了收藏本站喔。 接着前天的总结 习题21&#xff1a;函数可以返回某些东西 定义函数的加减乘除&#xff0c;以及嵌套使用 习题2…

PHP实现轻量级WEB服务器接收HTTP提交的RFID刷卡信息并回应驱动读卡器显示播报语音

本示例使用的读卡器&#xff1a;RFID网络WIFI无线TCP/UDP/HTTP可编程二次开发读卡器POE供电语音-淘宝网 (taobao.com) <?php mb_http_output(utf-8); $port88; $socket socket_create(AF_INET, SOCK_STREAM, SOL_TCP); $bool socket_bind($socket, "0.0.0.0",…

深度学习入门-3-计算机视觉-卷积神经网络

一、计算机视觉 1.概述 计算机视觉作为一门让机器学会如何去“看”的学科&#xff0c;具体的说&#xff0c;就是让机器去识别摄像机拍摄的图片或视频中的物体&#xff0c;检测出物体所在的位置&#xff0c;并对目标物体进行跟踪&#xff0c;从而理解并描述出图片或视频里的场…

Python进阶系列(二)— 类与对象

对象 Python是一个面向对象的语言Python的内置类型实例都是对象对象包含数据和方法集合 类 类是对现实中的事物进行抽象的数据表示&#xff0c;用来定义对象们的数据结构&#xff0c;对象由实例化类获得。 例如这是一个玩家类&#xff0c;玩家有x&#xff0c;y和生命值三个…

程序的机器级表示

程序的机器级表示 程序编码数据格式访问信息的方式 所有的高级语言&#xff0c;都会被计算机翻译为机器代码&#xff0c;然后再根据汇编代码生成可执行的机器代码。二进制的机器代码我们人类肯定是读不懂了&#xff0c;但是汇编代码还是可以简单了解一下的。CPU 的 PC、寄存器、…