版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
OpenCV初识代码详解实验要求任务简介010203基本任务任务简介OpenCV(OpenSourceComputerVisionLibrary)是一个开源的计算机视觉和机器学习软件库。OpenCV旨在为计算机视觉应用提供通用基础架构,并加速机器感知在商业产品中的应用。这个库拥有超过2500种的优化算法,涵盖了经典的和最先进的计算机视觉和机器学习算法。OpenCV拥有超过47,000人的用户社区和超过1400万的估计下载量。该库被公司,研究团体和政府机构广泛使用。Opencv
模块简介任务简介实验任务:读取一张图片并显示代码详解实验要求流程简介010203read_and_show_image.py代码详解#在使用OpenCV前需要先安装对应python环境importcv2#读取一张图片(图片路径要自己指定)lena=cv2.imread("1.png",1)#在指定窗口显示(图片路径要自己指定)cv2.imshow("image",lena)cv2.waitKey(0)cv2.destroyAllWindows()代码详解实验要求流程简介010203实验要求1.读取任意一张图片并以个人名字拼音缩写为窗口名显示2.分析下如何可以将彩色图片显示为灰度图。3.分析下如何可以让显示窗口的大小为400*500分辨率相机标定代码详解实验要求任务简介010203基本任务任务简介在图像测量过程以及机器视觉应用中,必须建立相机成像的几何模型,即相机参数。求解参数(内参、外参、畸变参数)的过程就称之为相机标定。实验流程任务简介1)准备标定板、相机不同角度和距离拍下的标定板的数据2)检测图像中的特征点3)估计相机内参、外参和畸变系数4)图像去畸不断改变需要标定的相机相对于标定板的位姿,采集20-40帧的图像(图像将统一提供)数据准备代码详解实验要求流程简介010203代码详解相机标定官方历程双目标定官方历程GitHub:/opencv/opencv/定义棋盘格尺寸(内角点数,角点间真实距离)2.读取相机采集的标定板图像(至少2张,20-40张即可)3.寻找每帧标定板的角点,细化像素坐标,绘制角点,计算角点在世界坐标系下的坐标found=findChessboardCorners(view,s.boardSize,pointBuf,chessBoardFlags);cvtColor(view,viewGray,COLOR_BGR2GRAY);cornerSubPix(viewGray,pointBuf,Size(winSize,winSize),Size(-1,-1),TermCriteria(TermCriteria::EPS+TermCriteria::COUNT,30,0.0001));drawChessboardCorners(view,s.boardSize,Mat(pointBuf),found);使用opencv进行相机标定:camera_calibration.cpp代码详解使用opencv进行相机标定:camera_calibration.cpp代码详解4.计算相机内参矩阵和畸变系数rms=calibrateCameraRO(objectPoints,imagePoints,imageSize,iFixedPoint,cameraMatrix, distCoeffs,rvecs,tvecs,newObjPoints,s.flag|CALIB_USE_LU);5.畸变矫正
initUndistortRectifyMap(cameraMatrix,distCoeffs,Mat(),
getOptimalNewCameraMatrix(cameraMatrix,distCoeffs,imageSize,1,imageSize,0),imageSize,CV_16SC2,map1,map2);remap(view,rview,map1,map2,INTER_LINEAR);MATLAB版本操作内容导入相机采集的标定板图像并设置格子长度(至少2张,20-40张即可)Step1Step2Step3MATLAB版本操作内容2.设置相机类型和畸变参数形式并进行标定MATLAB版本操作内容3.设置相机类型和畸变参数形式并进行标定外参可视化显示每一帧图像相对于相机的位姿(标定采数据时位姿要充分变化)可调整阈值,移除平均像素误差较大的帧MATLAB版本数据分析畸变系数(径向k、切向p)相机内参矩阵(MATLAB输出为转置)代码详解实验要求流程简介010203实验要求完成相机标定实验(编程语言可使用C++/python)对相机标定结果进行定量分析理论推导分析图像分辨率的改变对其标定结果的影响传统图像检测与分割代码详解实验要求任务简介010203基本任务任务简介1、使用Robert算子、Sobel算子、Prewitt算子、Kirsch算子和Canny边缘检测算法提取图像边缘,并对比这几种算法处理图像的效果2、使用基本的全局阈值算法和Otsu算法对图像进行分割,并对比两者分割图像的效果原图Canny边缘检测原图全局阈值Otsu一阶微分算子与边缘检测任务简介Robert算子Prewitt算子和Sobel算子模板
一阶微分算子与边缘检测任务简介Kirsch算子
Canny边缘检测算法任务简介Canny边缘检测算法可以归纳为以下四个步骤:(1)用高斯滤波器平滑图像,去除实际图像信号中存在噪声;(2)用一阶偏导的有限差分来计算梯度的幅值和方向,但经过滤波操作之后,虽然能够在一定程度上抑制噪声,也会使图像变得模糊,从而导致提取的边缘具有一定的宽度;(3)对梯度幅值进行非极大值抑制,使得边缘变细;(4)用双阈值算法检测和连接边缘,将非极大值抑制产生的边缘点连接起来,同时去除孤立的噪声点产生的假边缘。5x5的高斯模板基本的全局阈值处理任务简介
全局阈值是指整幅图像使用同一个阈值做分割处理,适用于背景和前景有明显对比的图像Otsu算法任务简介
Otsu方法又称作最大类间方差法,是一种确定图像二值化分割最佳阈值的算法,由日本学者大津于1979年提出。其基本思想上求得一个阈值T,使得前景与背景图像的类间方差最大。Otsu方法计算简单,不受图像亮度和对比度的影响,在数字图像处理上得到了广泛的应用。代码详解实验要求流程简介010203边缘检测:edge_detection.py代码详解fromscipyimportndimagefrommatplotlibimportpyplotasplt
importcv2
importnumpyasnp
#
使用cv2包实现边缘检测
#
读取灰度图像
image=cv2.imread('test/test.jpg',0)#定义存储边缘检测图像的字典
methods={"Original":image,"Roberts":None,"Prewitt":None,"Sobel":None,"Kirsch":None,"Canny":None}
#应用边缘检测
methods["Roberts"]=roberts_cross(image)
methods["Prewitt"]=prewitt(image)
methods["Sobel"]=sobel(image)
methods["Kirsch"]=kirsch(image)
methods["Canny"]=canny(image)
#保存结果
cv2.imwrite('test/edges_roberts.jpg',methods["Roberts"])
cv2.imwrite('test/edges_prewitt.jpg',methods["Prewitt"])
cv2.imwrite('test/edges_sobel.jpg',methods["Sobel"])
cv2.imwrite('test/edges_kirsch.jpg',methods["Kirsch"])
cv2.imwrite('test/edges_canny.jpg',methods["Canny"])
#显示原始图像和边缘检测结果
plt.figure(figsize=(12,8))
fori,(name,edge_image)inenumerate(methods.items()):
plt.subplot(2,3,i+1)
plt.title(f'{name}EdgeDetection')
plt.imshow(edge_image,cmap='gray')
plt.axis('off')#Robert算子defroberts(image,):
roberts_cross_v=np.array([[1,0],[0,-1]],dtype=np.float32)
roberts_cross_h=np.array([[0,1],[-1,0]],dtype=np.float32)
vertical_roberts=cv2.filter2D(image,cv2.CV_32F,roberts_cross_v)
horizontal_roberts=cv2.filter2D(image,cv2.CV_32F,roberts_cross_h)
edges_roberts=np.sqrt(np.square(vertical_roberts)+np.square(horizontal_roberts))
edges_binary=np.zeros_like(edges_roberts)
edges_binary[edges_roberts>=50]=255
returnedges_binary
#Prewitt算子
defprewitt(image):
prewitt_kernel_v=np.array([[1,1,1],[0,0,0],[-1,-1,-1]],dtype=np.float32)
prewitt_kernel_h=np.array([[-1,0,1],[-1,0,1],[-1,0,1]],dtype=np.float32)
vertical_prewitt=cv2.filter2D(image,cv2.CV_32F,prewitt_kernel_v)
horizontal_prewitt=cv2.filter2D(image,cv2.CV_32F,prewitt_kernel_h)
edges_prewitt=np.sqrt(np.square(vertical_prewitt)+np.square(horizontal_prewitt))
edges_binary=np.zeros_like(edges_prewitt)
edges_binary[edges_prewitt>=200]=255
returnedges_binary#Sobel算子defsobel(image):
x=cv2.Sobel(image,cv2.CV_64F,1,0,ksize=3)
y=cv2.Sobel(image,cv2.CV_64F,0,1,ksize=3)
edge_magnitude=np.sqrt(x**2+y**2)
edges_binary=np.zeros_like(edge_magnitude)
edges_binary[edge_magnitude>=200]=255
returnedges_binary
#Kirsch算子
defkirsch(image):
kirsch_kernels=[
np.array([[5,5,5],[-3,0,-3],[-3,-3,-3]],dtype=np.float32),
np.array([[-3,5,5],[-3,0,5],[-3,-3,-3]],dtype=np.float32),
np.array([[-3,-3,5],[-3,0,5],[-3,-3,5]],dtype=np.float32),
np.array([[-3,-3,-3],[-3,0,5],[-3,5,5]],dtype=np.float32),
np.array([[-3,-3,-3],[-3,0,-3],[5,5,5]],dtype=np.float32),
np.array([[-3,-3,-3],[5,0,-3],[5,5,-3]],dtype=np.float32),
np.array([[5,-3,-3],[5,0,-3],[5,-3,-3]],dtype=np.float32),
np.array([[5,5,-3],[5,0,-3],[-3,-3,-3]],dtype=np.float32),
]
edges_kirsch=np.zeros_like(image,dtype=np.float32)
forkernelinkirsch_kernels:
filtered=cv2.filter2D(image,cv2.CV_32F,kernel)
edges_kirsch=np.maximum(edges_kirsch,filtered)
edges_binary=np.zeros_like(edges_kirsch)
edges_binary[edges_kirsch>=255]=255
returnedges_binary
#Canny算子
defcanny(image):
returncv2.Canny(image,100,200)edge_detection.py代码详解#对梯度幅值进行非极大值抑制defnon_maximum_suppression(grad_mag,grad_dir):
M,N=grad_mag.shape
Z=np.zeros((M,N),dtype=np.float32)
angle=grad_dir
foriinrange(1,M-1):
forjinrange(1,N-1):
try:
q,r=255,255
#angle0
if(0<=angle[i,j]<22.5)or(157.5<=angle[i,j]<=180):
q=grad_mag[i,j+1]
r=grad_mag[i,j-1]
#angle45
elif(22.5<=angle[i,j]<67.5):
q=grad_mag[i+1,j-1]
r=grad_mag[i-1,j+1]
#angle90
elif(67.5<=angle[i,j]<112.5):
q=grad_mag[i+1,j]
r=grad_mag[i-1,j]
#angle135
elif(112.5<=angle[i,j]<157.5):
q=grad_mag[i-1,j-1]
r=grad_mag[i+1,j+1]
if(grad_mag[i,j]>=q)and(grad_mag[i,j]>=r):
Z[i,j]=grad_mag[i,j]
else:
Z[i,j]=0
exceptIndexErrorase:
pass
returnZ
#双阈值检测defdouble_threshold(img,lowThreshold,highThreshold):
highThreshold=img.max()*highThreshold
lowThreshold=highThreshold*lowThreshold
M,N=img.shape
res=np.zeros((M,N),dtype=32)
strong_i,strong_j=np.where(img>=highThreshold)
weak_i,weak_j=np.where((img<=highThreshold)&(img>=lowThreshold))
res[strong_i,strong_j]=255
res[weak_i,weak_j]=75
return(res,75,255)
#边缘连接
defhysteresis(img,weak,strong=255):
M,N=img.shape
foriinrange(1,M-1):
forjinrange(1,N-1):
if(img[i,j]==weak):
if((img[i+1,j-1]==strong)or(img[i+1,j]==strong)or(img[i+1,j+1]==strong)
or(img[i,j-1]==strong)or(img[i,j+1]==strong)
or(img[i-1,j-1]==strong)or(img[i-1,j]==strong)or(img[i-1,j+1]==strong)):
img[i,j]=strong
else:
img[i,j]=0
returnimg#
按步骤自行编写函数实现Canny边缘检测defcanny(image):
#1.用高斯滤波器平滑图像
blurred_image=cv2.GaussianBlur(image,(5,5),1.4)
#2.用一阶偏导的有限差分来计算梯度的幅值和方向
#计算x方向和y方向的梯度
grad_x=cv2.Sobel(blurred_image,cv2.CV_64F,1,0,ksize=3)
grad_y=cv2.Sobel(blurred_image,cv2.CV_64F,0,1,ksize=3)
#计算梯度幅值和方向
gradient_magnitude=np.sqrt(grad_x**2+grad_y**2)
gradient_direction=np.arctan2(grad_y,grad_x)*(180/np.pi)
gradient_direction[gradient_direction<0]+=180
#3.对梯度幅值进行非极大值抑制
nms=non_maximum_suppression(gradient_magnitude,gradient_direction)
#4.用双阈值算法检测和连接边缘
#双阈值检测
thresholded,weak,strong=double_threshold(nms,0.05,0.15)
#边缘连接
edge_final=hysteresis(thresholded,weak,strong)
edge_final_uint8=cv2.convertScaleAbs(edge_final)
returnedge_final_uint8代码详解可视化示例:实验数据:经典灰度图像代码详解传统阈值分割:segment.py代码详解importcv2
importmatplotlib.pyplotasplt
#读取图像
image=cv2.imread('woman_blonde.tif',0)
#全局阈值算法
_,global_thresh=cv2.threshold(image,127,255,cv2.THRESH_BINARY)
#Otsu算法
_,otsu_thresh=cv2.threshold(image,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
#保存分割后的图像
cv2.imwrite('global_threshold.png',global_thresh)
cv2.imwrite('otsu_threshold.png',otsu_thresh)
#可视化
titles=['OriginalImage','GlobalThreshold','OtsuThreshold']
images=[image,global_thresh,otsu_thresh]
plt.figure(figsize=(12,4))
fori,(title,img)inenumerate(zip(titles,images),1):
plt.subplot(1,3,i)
plt.imshow(img,cmap='gray')
plt.title(title)
plt.axis('off')
plt.tight_layout()
plt.show()代码详解可视化示例:实验数据:经典图像代码详解代码详解实验要求流程简介010203实验要求1.将指定实验图像转化为灰度图像,并绘制出它的灰度直方图2.在edge_detection.py的基础上,调用不同的微分算子函数提取图像的边缘特征,并可视化。撰写实验报告分析这些不同微分算子函数对边缘特征提取的影响。
3.调用cv库中的canny函数,与自己编写的canny算法结果进行对比4.运行segment.py,对数据集进行全局阈值分割和otus阈值分割,对比两者的区别5.在4的基础上,将图像分成4和8个小块,对每一个块进行阈值分割,并与4的结果进行对比每一步都请在实验报告上写明完成过程双目视觉代码详解实验要求任务简介010203基本任务任务简介立体视觉(也称双目视觉)主要研究的两个相机的成像几何问题,研究内容主要包括:立体标定(StereoCalibration)、立体校正(StereoRectification)和立体匹配(StereoMatching)。任务简介双目矫正双目矫正主要包括两方面:畸变矫正和立体矫正畸变矫正:主要用于去除图像畸变(参考上个实验)立体矫正:实际应用中,两个相机摆放一定是不平行的,因而相平面中的极线大概率是条斜线,这就给搜索过程带来了不便,为了简化过程,还需要引入额外的极线矫正步骤,使得两相机的极线共线且平行于相平面的x轴任务简介立体匹配流程匹配代价计算代价聚合视差计算传统的立体匹配算法包括BM(Block
Matching)、SGBM(Semi-GlobalBlockMatching)和GC(GraphCut)算法视差效果比较
BM<SGBM<GC处理速度比较
BM>SGBM>GC综合考虑,后面算法采用SGBM算法作为示范图像类型比较
BM(灰度)SGBM(24bit彩色)GC(灰度)
实验流程任务简介1)准备标定板、双目相机不同角度和距离拍下的标定板的数据2)标定双目相机3)立体矫正4)立体匹配获得视差图5)恢复深度图与深度点云双目标定与矫正立体匹配深度恢复代码详解实验要求流程简介010203代码详解双目标定官方例程立体匹配官方例程使用opencv进行双目标定:stereo_calib.cpp代码详解1)双目相机的内参与外参标定cv::CommandLineParserparser(argc,argv,"{w|9|}{h|6|}{s|1.0|}{nr||}{help||}{@input|stereo_calib.xml|}");found=findChessboardCorners()rms=stereoCalibrate()2)立体矫正stereoRectify()initUndistortRectifyMap()remap()3)评估(极线几何约束)M1D1M2D2RTintrinsics.ymlextrinsics.ymlR1R2P1P2Q1)设定双目相机内参外参和算法参数2)SGBM参数调整sgbm->setPreFilterCap(31);
//预处理滤波器截断值等sgbm->setBlockSize(winSize);
//SAD窗口大小sgbm->setP1(8*pngChannels*winSize*winSize);
//控制视差平滑度第一参数sgbm->setP2(32*pngChannels*winSize*winSize);
//控制视差平滑度第二参数sgbm->setMinDisparity(0);
//最小视差sgbm->setNumDisparities(nmDisparities);
//视差搜索范围sgbm->setUniquenessRatio(5);
//视差唯一性百分比sgbm->setSpeckleWindowSize(100);
//检查视差连通区域变化度的窗口大小sgbm->setSpeckleRange(32);
//视差变化阈值,当窗口内视差变化大于阈值时窗口内的视差清零sgbm->setDisp12MaxDiff(1);
//左右视差图最大容许差异,超过该阈值的视差值将被清零sgbm->setMode(cv::StereoSGBM::MODE_SGBM);
//采用全尺寸双通道动态编程算法3)双目相机的内参与外参标定sgbm->compute(img1,img2,disp);立体匹配:stereo_match.cpp代码详解视差图disp使用opencv进行相机标定:camera_calibration.cpp代码详解1)生成深度图depth=fx*base_line/disparity2)生成点云cv::reprojectImageTo3D(floatDisp,xyz,Q,true);cv::saveXYZ(point_cloud_filename.c_str(),xyz);代码详解实验要求流程简介010203实验要求完成双目立体视觉实验,实现图像去畸、视差图计算对双目标定结果进行定量分析,分析sgbm算法中某1个参数对实验效果的影响3.可视化展示,即深度图着色与点云结果展示4.分析当双目的内参不一样,能否通过图像变换,使其变为一样。如果可以,分析将内参变为一致有什么好处,公式推导结论,并实验验证。特征匹配代码详解实验要求任务简介010203基本任务任务简介一幅图像中总存在着其独特的像素点,这些点我们可以认为就是这幅图像的特征,成为特征点。特征点应用在目标识别、图像配准、视觉跟踪、三维重建任务等。原理为从图像中选取某些特征点并对图像进行局部分析,而非观察整幅图像。实验流程任务简介1)准备一组连续图像序列2)提取图像中特征点3)将帧间相似的特征点进行匹配4)筛选特征,去除错误匹配特征筛选特征点提取特征点匹配任务简介特征点提取图像特征算法:ORB(OrientedFastandRotatedBrief)作用:对图像中的关键点快速创建特征向量特点:计算速度快,特征满足缩放旋转不变性1.FAST(关键点检测):根据像素值变化检测图像中突出的小区域,如角点、边缘等。2.rBRIEF(特征描述子创建):为每个关键点计算相应的特征向量。ORB算法创建的特征向量只包含1和0,表示关键点周围的强度模式。特征点匹配模式匹配算法:BF(Brute-Force)作用:对多张图像中相同的特征点一一对应起来。通常匹配时是求解描述子的距离,在ORB特征匹配过程中采用的是Hamming距离。代码详解实验要求流程简介010203代码详解特征匹配官方例程GitHub:/opencv/opencv/特征匹配:matchmethod_orb_akaze_brisk.cpp代码详解1)读取图片并转为灰度Matimg1=cv::imread(fileName[0],IMREAD_GRAYSCALE);Matimg2=cv::imread(fileName[1],IMREAD_GRAYSCALE);2)选择特征提取算法Ptr<Feature2D>b;b=cv::ORB::create();3)计算特征点b->detect(img1,keyImg1,Mat());b->compute(img1,keyImg1,descImg1);或者:b->detectAndCompute(img2,Mat(),keyImg2,descImg2,false);特征匹配:matchmethod_orb_akaze_brisk.cpp代码详解4)选取特征匹配算法descriptorMatcher=DescriptorMatcher::create(“BruteForce”);5)特征匹配descriptorMatcher->match(descImg1,descImg2,matches,Mat());6)可视化cv::drawMatches(img1,keyImg1,img2,keyImg2,bestMatches,result);代码详解实验要求流程简介010203实验要求完成图像特征点提取与匹配实验实现特征筛选思考如果已知机器人是平面运动,是否存在提高匹配准确率的方法,请理论分析并实验验证利用对极几何约束求解相机运动代码详解实验要求任务简介010203基本任务任务简介基于已经匹配好的2D特征点,利用对极几何约束进行2D-2D的相机运动估计。对极几何约束任务简介
对极几何约束任务简介
代码详解实验要求流程简介010203pose_estimation_2d2d.cpp代码详解#include
<iostream>#include
<opencv2/core/core.hpp>#include
<opencv2/features2d/features2d.hpp>#include
<opencv2/highgui/highgui.hpp>#include
<opencv2/calib3d/calib3d.hpp>//#include"extra.h"//usethisifinOpenCV2
using
namespacestd;using
namespacecv;
void
find_feature_matches(
const
Mat&img_1,const
Mat&img_2,
std::vector<KeyPoint>&keypoints_1,
std::vector<KeyPoint>&keypoints_2,
std::vector<DMatch>&matches);
voidpose_estimation_2d2d(
std::vector<KeyPoint>keypoints_1,
std::vector<KeyPoint>keypoints_2,
std::vector<DMatch>matches,
Mat&R,Mat&t);//像素坐标转相机归一化坐标Point2d
pixel2cam(const
Point2d&p,const
Mat&K);int
main(int
argc,char**argv){
if(argc!=3){
cout<<"usage:pose_estimation_2d2dimg1img2"<<endl;
return
1;
}
//--读取图像
Matimg_1=imread(argv[1],CV_LOAD_IMAGE_COLOR);
Matimg_2=imread(argv[2],CV_LOAD_IMAGE_COLOR);
assert(img_1.data&&img_2.data&&"Cannotloadimages!");
vector<KeyPoint>keypoints_1,keypoints_2;
vector<DMatch>matches;
find_feature_matches(img_1,img_2,keypoints_1,keypoints_2,matches);
cout<<"一共找到了"
<<matches.size()<<"组匹配点"
<<endl;
//--估计两张图像间运动
MatR,t;
pose_estimation_2d2d(keypoints_1,keypoints_2,matches,R,t);
//--验证E=t^R*scale
Matt_x=
(Mat_<double>(3,3)<<0,-t.at<double>(2,0),t.at<double>(1,0),
t.at<double>(2,0),0,-t.at<double>(0,0),
-t.at<double>(1,0),t.at<double>(0,0),0);
cout<<"t^R="<<endl<<t_x*R<<endl;
//--验证对极约束
MatK=(Mat_<double>(3,3)<<520.9,0,325.1,0,521.0,249.7,0,0,1);
for(DMatchm:matches){
Point2dpt1=pixel2cam(keypoints_1[m.queryIdx].pt,K);
Maty1=(Mat_<double>(3,1)<<pt1.x,pt1.y,1);
Point2dpt2=pixel2cam(keypoints_2[m.trainIdx].pt,K);
Maty2=(Mat_<double>(3,1)<<pt2.x,pt2.y,1);
Matd=y2.t()*t_x*R*y1;
cout<<"epipolarconstraint="<<d<<endl;
}
return
0;}pose_estimation_2d2d.cpp代码详解void
find_feature_matches(
const
Mat&img_1,const
Mat&img_2,
std::vector<KeyPoint>&keypoints_1,
std::vector<KeyPoint>&keypoints_2,
std::vector<DMatch>&matches){
//--初始化
Matdescriptors_1,descriptors_2;
//usedinOpenCV3
Ptr<FeatureDetector>detector=ORB::create();
Ptr<DescriptorExtractor>descriptor=ORB::create();
//usethisifyouareinOpenCV2
//Ptr<FeatureDetector>detector=FeatureDetector::create("ORB");
//Ptr<DescriptorExtractor>descriptor=DescriptorExtractor::create("ORB");
Ptr<DescriptorMatcher>matcher=DescriptorMatcher::create("BruteForce-Hamming");
//--第一步:检测OrientedFAST角点位置
detector->detect(img_1,keypoints_1);
detector->detect(img_2,keypoints_2);
//--第二步:根据角点位置计算BRIEF描述子
descriptor->compute(img_1,keypoints_1,descriptors_1);
descriptor->compute(img_2,keypoints_2,descriptors_2);
//--第三步:对两幅图像中的BRIEF描述子进行匹配,使用Hamming距离
vector<DMatch>match;
//BFMatchermatcher(NORM_HAMMING);
matcher->match(descriptors_1,descriptors_2,match);
//--第四步:匹配点对筛选
double
min_dist=10000,max_dist=0;
//找出所有匹配之间的最小距离和最大距离,即是最相似的和最不相似的两组点之间的距离
for(int
i=0;i<descriptors_1.rows;i++){
double
dist=match[i].distance;
if(dist<min_dist)min_dist=dist;
if(dist>max_dist)max_dist=dist;
}
printf("--Maxdist:%f
\n",max_dist);
printf("--Mindist:%f
\n",min_dist);
//当描述子之间的距离大于两倍的最小距离时,即认为匹配有误.但有时候最小距离会非常小,设置一个经验值30作为下限.
for(int
i=0;i<descriptors_1.rows;i++){
if(match[i].distance<=max(2*min_dist,30.0)){
matches.push_back(match[i]);
}
}}Point2d
pixel2cam(const
Point2d&p,const
Mat&K){
return
Point2d(
(p.x-K.at<double>(0,2))/K.at<double>(0,0),
(p.y-K.at<double>(1,2))/K.at<double>(1,1)
);}pose_estimation_2d2d.cpp代码详解voidpose_estimation_2d2d(
std::vector<KeyPoint>keypoints_1,
std::vector<KeyPoint>keypoints_2,
std::vector<DMatch>matches,
Mat&R,Mat&t){
//相机内参,TUMFreiburg2
MatK=(Mat_<double>(3,3)<<520.9,0,325.1,0,521.0,249.7,0,0,1);
//--把匹配点转换为vector<Point2f>的形式
vector<Point2f>points1;
vector<Point2f>points2;
for(inti=0;i<(int)matches.size();i++){
points1.push_back(keypoints_1[matches[i].queryIdx].pt);
points2.push_back(keypoints_2[matches[i].trainIdx].pt);
}
//--计算基础矩阵
Matfundamental_matrix;
(**1**)
cout<<"fundamental_matrixis"<<endl<<fundamental_matrix<<endl;
//--计算本质矩阵
Point2dprincipal_point(325.1,249.7);
//相机光心,TUMdataset标定值
doublefocal_length=521;
//相机焦距,TUMdataset标定值
Matessential_matrix;
(**2**)
cout<<"essential_matrixis"<<endl<<essential_matrix<<endl;
//--从本质矩阵中恢复旋转和平移信息.
//此函数仅在Opencv3中提供
(**3**)
cout<<"Ris"<<endl<<R<<endl;
cout<<"tis"<<endl<<t<<endl;}试着补全此页高亮的三处关键代码,完成基础矩阵、本质矩阵以及旋转平移的计算。代码详解实验要求流程简介010203实验要求在理解对极几何原理的基础上,阅读pose_estimation_2d2d.cpp,并补全其中pose_estimation_2d2d函数的关键处代码。查阅相关资料,可调用第三方库编写代码,如OpenCV等。编译并运行程序,使用不同的图像对输入来验证其效果。每一步都请在实验报告上写明完成过程基于高斯牛顿法的LK光流估计代码详解实验要求任务简介010203基本任务任务简介基于高斯牛顿法,通过最小化灰度误差估计两张图像间的最优像素偏移,即LK光流。图像一:LK1.png图像二:LK2.png图:LK光流光度不变假设光流估计任务简介
任务简介光流估计图:KITTI数据上的光流估计结果
代码详解实验要求流程简介010203optical_flow.cpp代码详解#include
<opencv2/opencv.hpp>#include
<string>#include
<chrono>#include
<Eigen/Core>#include
<Eigen/Dense>
using
namespacestd;using
namespacecv;
stringfile_1="./LK1.png";
//firstimagestringfile_2="./LK2.png";
//secondimage
///Opticalflowtrackerandinterfaceclass
OpticalFlowTracker{public:
OpticalFlowTracker(
const
Mat&img1_,const
Mat&img2_,
const
vector<KeyPoint>&kp1_,vector<KeyPoint>&kp2_,
vector<bool>&success_,bool
inverse_=true,bool
has_initial_=false):
img1(img1_),img2(img2_),kp1(kp1_),kp2(kp2_),success(success_),inverse(inverse_),
has_initial(has_initial_){}
void
calculateOpticalFlow(const
Range&range);
private:
constMat&img1;
constMat&img2;
constvector<KeyPoint>&kp1;
vector<KeyPoint>&kp2;
vector<bool>&success;
boolinverse=true;
boolhas_initial=false;};void
OpticalFlowSingleLevel(
const
Mat&img1,
const
Mat&img2,
const
vector<KeyPoint>&kp1,
vector<KeyPoint>&kp2,
vector<bool>&success,
bool
inverse=false,
bool
has_initial_guess=false);
inline
float
GetPixelValue(constcv::Mat&img,float
x,float
y){
//boundarycheck
if(x<0)x=0;
if(y<0)y=0;
if(x>=img.cols-1)x=img.cols-2;
if(y>=img.rows-1)y=img.rows-2;
float
xx=x-floor(x);
float
yy=y-floor(y);
int
x_a1=std::min(img.cols-1,int(x)+1);
int
y_a1=std::min(img.rows-1,int(y)+1);
return(1-xx)*(1-yy)*img.at<uchar>(y,x)
+xx*(1-yy)*img.at<uchar>(y,x_a1)
+(1-xx)*yy*img.at<uchar>(y_a1,x)
+xx*yy*img.at<uchar>(y_a1,x_a1);}optical_flow.cpp代码详解int
main(int
argc,char**argv){
//images,notetheyareCV_8UC1,notCV_8UC3
Matimg1=imread(file_1,0);
Matimg2=imread(file_2,0);
//keypoints,usingGFTThere.
vector<KeyPoint>kp1;
Ptr<GFTTDetector>detector=GFTTDetector::create(500,0.01,20);
//maximum500keypoints
detector->detect(img1,kp1);
//nowletstrackthesekeypointsinthesecondimage
//firstusesinglelevelLKinthevalidationpicture
vector<KeyPoint>kp2_single;
vector<bool>success_single;
OpticalFlowSingleLevel(img1,img2,kp1,kp2_single,success_single);
//plot
Matimg2_single;
cv::cvtColor(img2,img2_single,CV_GRAY2BGR);
for(int
i=0;i<kp2_single.size();i++){
if(success_single[i]){
cv::circle(img2_single,kp2_single[i].pt,2,cv::Scalar(0,250,0),2);
cv::line(img2_single,kp1[i].pt,kp2_single[i].pt,cv::Scalar(0,250,0));
}
}
cv::imshow("trackedsinglelevel",img2_single);
cv::waitKey(0);
return
0;}void
OpticalFlowSingleLevel(
const
Mat&img1,
const
Mat&img2,
const
vector<KeyPoint>&kp1,
vector<KeyPoint>&kp2,
vector<bool>&success,
bool
inverse,bool
has_initial){
kp2.resize(kp1.size());
success.resize(kp1.size());
OpticalFlowTracker
tracker(img1,img2,kp1,kp2,success,inverse,has_initial);
parallel_for_(Range(0,kp1.size()),
std::bind(&OpticalFlowTracker::calculateOpticalFlow,&tracker,placeholders::_1));}optical_flow.cpp代码详解void
OpticalFlowTracker::calculateOpticalFlow(const
Range&range){
//parameters
int
half_patch_size=4;
int
iterations=10;
for(size_t
i=range.start;i<range.end;i++){
auto
kp=kp1[i];
double
dx=0,dy=0;//dx,dyneedtobeestimated
if(has_initial){
dx=kp2[i].pt.x-kp.pt.x;
dy=kp2[i].pt.y-kp.pt.y;
}
double
cost=0,lastCost=0;
bool
succ=true;//indicateifthispointsucceeded
//Gauss-Newtoniterations
Eigen::Matrix2dH=Eigen::Matrix2d::Zero();
//hessian
Eigen::Vector2db=Eigen::Vector2d::Zero();
//bias
Eigen::Vector2dJ;
//jacobian
for(int
iter=0;iter<iterations;iter++){
if(inverse==false){
H=Eigen::Matrix2d::Zero();
b=Eigen::Vector2d::Zero();
}else{
//onlyresetb
b=Eigen::Vector2d::Zero();
}
cost=0;
//computecostandjacobian
(**1**)
//computeupdate
(**2**)
//updatedx,dy
(**3**)
}
success[i]=succ;
//setkp2
kp2[i].pt=kp.pt+Point2f(dx,dy);
}}根据提示,试着补全此页高亮的三处关键代码。代码详解实验要求流程简介010
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年德阳市烟草专卖局人员招聘参考题库及答案详解
- 2026年内蒙古移动人员招聘考试备考题库及答案详解
- 2026年内蒙古移动人员招聘考试题库及答案详解
- 软件产业发展可行性研究报告模板范文怎么写
- 2026年国家能源集团重庆公司人员招聘笔试参考题库及答案详解
- 产业社区项目研究报告
- 2026年新余钢铁集团有限公司人员招聘考试备考试题及答案详解
- 2026年河南水利投资集团有限公司人员招聘考试备考试题及答案详解
- 2026年上犹县教师招聘笔试模拟试题及答案解析
- 2026福建中医药大学附属第二人民医院招聘高层次人才3人(二)考试备考题库及答案解析
- 2024年肺结核试题培训及答案
- 用电安全与人走断电规范
- 建筑装饰装修室内空间照明设计应用标准
- 《神经退行性疾病》课件
- 消防设施基本情况表
- GEVO型柴油机总组装与试验江利国课件
- 贵州省考试院2025年4月高三年级适应性考试化学试题及答案
- 2025年郑州铁路职业技术学院单招职业适应性测试题库必考题
- 水库施工便道合同
- 质量文化导论(华东理工大学)知到智慧树章节答案
- NB-T47023-2012长颈对焊法兰
评论
0/150
提交评论