摄像头定标一般都需要一个放在摄像头前的特制的标定参照物(棋盘纸),摄像头获取该物体的图像,并由此计算摄像头的内外参数。标定参照物上的每一个特征点相对于世界坐标系的位置在制作时应精确测定,世界坐标系可选为参照物的物体坐标系。在得到这些已知点在图像上的投影位置后,可计算出摄像头的内外参数。
如上公式所示,摄像头由于光学透镜的特性使得成像存在着径向畸变,可由三个参数k1,k2,k3确定;由于装配方面的误差,传感器与光学镜头之间并非完全平行,因此成像存在切向畸变,可由两个参数p1,p2确定。
cvStereoRectify 执行双目校正
initUndistortRectifyMap 分别生成两个图像校正所需的像素映射矩阵
cvremap 分别对两个图像进行校正
预处理: 图像归一化,减少亮度差别,增强纹理
stereoBM生成视差图
匹配过程: 滑动sad窗口,沿着水平线进行匹配搜索,由于校正后左右图片平行,左图的特征可以在右图对应行找到最佳匹配
再过滤: 去除坏的匹配点 通过uniquenessratio
输出视差图disparity:如果左右匹配点比较稠密,匹配点多,得到的图像与原图相似度比较大, 如果匹配点比较稀疏,得到的点与原图 相似度比较小
根据提取的特征点上用上述双目测距的相似三角算法得出距离。
我重新编译了Calibration那个程序,然后自己写了个批处理.bat文件,代码如下,删除txt,然后调用它del /f /q list_of_images_auto(bmp).txt
dir *.bmp /B >>list_of_images_auto(bmp).txt
OpenCV_Example_Calibration.exe -w 7 -h 8 -s 5 -o camera.txt -op -oe list_of_images_auto(bmp).txt
pause
其中-o camera.txt表示输出参数的文件名。
不过这样用着不爽。
你看源代码里面
cvWrite( fs, "camera_matrix", camera_matrix )
cvWrite( fs, "distortion_coefficients", dist_coeffs )
的地方,知道什么意思了吧,向txt里面写这两个参数
我后来是这么存的
cvSave("DistortionMatrix.xml",dist_coeffs)
cvSave("IntrinsicsMatrix.xml",camera_matrix)
这样下次调用的时候可以直接用矩阵拿来计算矫正
intrinsic = (CvMat*)cvLoad("IntrinsicsMatrix.xml")
distortion = (CvMat*)cvLoad("DistortionMatrix.xml")
。。。
cvInitUndistortMap(this->imgprocess.intrinsic, this->imgprocess.distortion, this->imgprocess.mapx, this->imgprocess.mapy)
等
以前有OPENCV的官网,可以下载到源代码的,我这边贴一个基于vc2005的源代码吧。#include <stdio.h>
#include<iostream>
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
using namespace std
int main( int argc, char** argv )
{
//声明IplImage指针
IplImage* pFrame = NULL
IplImage* pFrImg = NULL
IplImage* pBkImg = NULL
CvMat* pFrameMat = NULL
CvMat* pFrMat = NULL
CvMat* pBkMat = NULL
CvCapture* pCapture = NULL
int nFrmNum = 0
//创建窗口
cvNamedWindow("background",1)
cvNamedWindow("video", 1)
cvNamedWindow("foreground",1)
//排列窗口
cvMoveWindow("background", 30, 500)
cvMoveWindow("video", 350, 0)
cvMoveWindow("foreground", 690, 500)
//打开视频文件
if(argc == 2)
if( !(pCapture = cvCaptureFromFile(argv[1])))
{
fprintf(stderr, "文件打开错误", argv[1])
return -2
}
//逐帧读取视频
while(pFrame = cvQueryFrame( pCapture ))
{
nFrmNum++
//如果是第一帧,则申请内存,并初始化
if(nFrmNum == 1)
{
pBkImg = cvCreateImage(cvSize(pFrame->width, pFrame->height), IPL_DEPTH_8U,1)
pFrImg = cvCreateImage(cvSize(pFrame->width, pFrame->height), IPL_DEPTH_8U,1)
pBkMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1)
pFrMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1)
pFrameMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1)
//转化成单通道图
cvCvtColor(pFrame, pBkImg, CV_BGR2GRAY)
cvCvtColor(pFrame, pFrImg, CV_BGR2GRAY)
cvConvert(pFrImg, pFrameMat)
cvConvert(pFrImg, pFrMat)
cvConvert(pFrImg, pBkMat)
}
else
{
cvCvtColor(pFrame, pFrImg, CV_BGR2GRAY)
cvConvert(pFrImg, pFrameMat)
//平滑图像(高斯滤波)
cvSmooth(pFrameMat, pFrameMat, CV_GAUSSIAN, 3, 0, 0)
//当前帧减去背景
cvAbsDiff(pFrameMat, pBkMat, pFrMat)
//前景图二值化
cvThreshold(pFrMat, pFrImg, 60, 255.0, CV_THRESH_BINARY)
//形态学滤波(去噪音)
cvErode(pFrImg, pFrImg, 0, 1)
cvDilate(pFrImg, pFrImg, 0, 1)
//把图像转正
pBkImg->origin=1
pFrImg->origin=1
//对pFrImg上的已经识别出的运动物体,在pFrame上画跟踪框
int x,y
for (y=pFrImg->height - 1y>=250y--)
{
uchar* ptr = (uchar*)(pFrImg->imageData+pFrImg->widthStep*y)//将imageData指针指向第y行头部
for (x=0x<pFrImg->widthx++)
{
if(ptr[x]!=0)//判断地y行第x个元素是否有图像,如果有图像,则画跟踪框
{
CvPoint pt1_Rect
CvPoint pt2_Rect
pt1_Rect.x=x-30
pt1_Rect.y=y
pt2_Rect.x=x+30
pt2_Rect.y=y-300
int thickness=3
int line_type=8
CvScalar color=CV_RGB(255,0,0)
cvRectangle( pFrame, pt1_Rect, pt2_Rect,color ,thickness, line_type, 0 )
y=-1
break
}
}
}
//显示图像
cvShowImage("video", pFrame)
cvShowImage("background", pBkImg)
cvShowImage("foreground", pFrImg)
//如果有按键事件,则跳出循环
//为cvShowImage函数提供时间完成显示
//等待时间可以根据CPU速度调整
if( cvWaitKey(27) >= 0 )
break
}
}
//销毁窗口
cvDestroyWindow("video")
cvDestroyWindow("background")
cvDestroyWindow("foreground")
//释放图像和矩阵
cvReleaseImage(&pFrImg)
cvReleaseImage(&pBkImg)
cvReleaseMat(&pFrameMat)
cvReleaseMat(&pFrMat)
cvReleaseMat(&pBkMat)
cvReleaseCapture(&pCapture)
return 0
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)