单目相机标定、图像校正、单目位姿估计、差值法检测移动物体、稠密光流法跟踪移动物体

目录

1、单目相机标定

2、图像校正

3、单目位姿估计

4、差值法检测移动物体

5、稠密光流法跟踪移动物体


1、单目相机标定

单目相机标定、图像校正、单目位姿估计、差值法检测移动物体、稠密光流法跟踪移动物体_第1张图片

 单目相机标定、图像校正、单目位姿估计、差值法检测移动物体、稠密光流法跟踪移动物体_第2张图片

 单目相机标定、图像校正、单目位姿估计、差值法检测移动物体、稠密光流法跟踪移动物体_第3张图片

 单目相机标定、图像校正、单目位姿估计、差值法检测移动物体、稠密光流法跟踪移动物体_第4张图片

 单目相机标定、图像校正、单目位姿估计、差值法检测移动物体、稠密光流法跟踪移动物体_第5张图片

 单目相机标定、图像校正、单目位姿估计、差值法检测移动物体、稠密光流法跟踪移动物体_第6张图片

 

//单目相机标定
int test1()
{
	//读取所有图像
	vector imgs;
	string imageName;
	ifstream fin("F:/testMap/calibdate.txt");
	while(getline(fin, imageName))
	{
		Mat img = imread(imageName);
		imgs.push_back(img);
	}
	Size board_size = Size(9, 6);//方格标定板内角点数目(行,列)
	vector> imgsPoints;
	//提取每张图像内角点坐标
	for (int i = 0; i < imgs.size(); i++)
	{
		Mat img1 = imgs[i];
		Mat gray1;
		cvtColor(img1, gray1, COLOR_BGR2GRAY);
		vector img1_points;
		findChessboardCorners(gray1, board_size, img1_points);//计算方格标定板角点
		find4QuadCornerSubpix(gray1, img1_points, Size(5, 5));//细化方格标定板角点坐标
		bool pattern = true;
		drawChessboardCorners(img1, board_size, img1_points, pattern);
		imshow("img1", img1);
		waitKey(0);
		imgsPoints.push_back(img1_points);
	}

	//生成棋盘格每个内角点的空间三维坐标
	Size squareSize = Size(10, 10);//棋盘格每个方格的真实尺寸
	vector> objectPoints;

	for (int i = 0; i < imgsPoints.size(); i++)
	{
		vector tempPointSet;
		for (int j = 0; j < board_size.height; j++)
		{
			for (int k = 0; k < board_size.width; k++)
			{
				Point3f realPoint;
				//假设标定板为世界坐标系的z平面,即z = 0
				realPoint.x = j*squareSize.width;
				realPoint.y = k*squareSize.height; realPoint.z = 0;
				tempPointSet.push_back(realPoint);
			}
		}
		objectPoints.push_back(tempPointSet);
	}

	//图像尺寸
	Size imageSize;
	imageSize.width = imgs[0].cols;
	imageSize.height = imgs[0].rows;
	Mat cameraMatrix = Mat(3, 3, CV_32FC1, Scalar::all(0));//摄像机内参数矩阵
	Mat distCoeffs = Mat(1, 5, CV_32FC1, Scalar::all(0));//摄像机的5个畸变系数:k1,k2,p1,p2, k3
	vector rvecs;//每幅图像的旋转向量
	vector tvecs;//每张图像的平移量
	calibrateCamera(objectPoints, imgsPoints, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs, 0);
	cout << "相机的内参矩阵=" << endl << cameraMatrix << endl;
	cout << "相机畸变系数" << distCoeffs << endl;

	waitKey(0);
	return 0;
}

2、图像校正

单目相机标定、图像校正、单目位姿估计、差值法检测移动物体、稠密光流法跟踪移动物体_第7张图片

 单目相机标定、图像校正、单目位姿估计、差值法检测移动物体、稠密光流法跟踪移动物体_第8张图片

 

//图像校正
//用undistort()函数直接计算校正图像
//所有原图像向量  计算得到的相机内参  计算得到的相机畸变系数 校正后的输出图像
void undist(vector imgs, Mat cameraMatrix, Mat distCoeffs, vector &undistImgs)
{
	for (int i = 0; i < imgs.size(); i++)
	{
		Mat undistImg;
		undistort(imgs[i], undistImg, cameraMatrix, distCoeffs);
		undistImgs.push_back(undistImg);
	}
}
int test2()
{
	//读取所有图像
	vector imgs; 
	string imageName;
	ifstream fin("F:/testMap/calibdate.txt");
	while (getline(fin, imageName))
	{
		Mat img = imread(imageName);
		imgs.push_back(img);
	}

	//输入前文计算得到的内参矩阵
	Mat cameraMatrix = (Mat_(3, 3) << 532.016297, 0, 332.172519,
		0, 531.565159, 233.388075,
		0, 0, 1);

	//输入前文计算得到的畸变矩阵
	Mat distCoeffs = (Mat_(1, 5) << -0.285188, 0.080097, 0.001274, -0.002415, 0.106579);

	vector undistImgs;
	Size imageSize;
	imageSize.width = imgs[0].cols;
	imageSize.height = imgs[0].rows;

	//用undistort()函数直接计算校正图像,下一行代码取消注释即可
	undist(imgs, cameraMatrix, distCoeffs, undistImgs);

	//显示校正前后的图像
	for (int i = 0; i < imgs.size(); i++)
	{
		string windowNumber = to_string(i);
		imshow("未校正图像" + windowNumber, imgs[i]);
		imshow("校正后图像" + windowNumber, undistImgs[i]); waitKey(0);
		destroyWindow("未校正图像" + windowNumber);
		destroyWindow("校正后图像" + windowNumber);
	}

	waitKey(0);
	return 0;
}

3、单目位姿估计

单目相机标定、图像校正、单目位姿估计、差值法检测移动物体、稠密光流法跟踪移动物体_第9张图片

单目相机标定、图像校正、单目位姿估计、差值法检测移动物体、稠密光流法跟踪移动物体_第10张图片 

 

//单目位姿估计
int test3()
{
	//读取所有图像
	Mat img = imread("F:/testMap/left01.png");
	Mat gray;
	cvtColor(img,gray,COLOR_BGR2GRAY); 
	vector imgPoints;
	Size boardSize = Size(9,6);
	findChessboardCorners(gray,boardSize, imgPoints);//计算方格标定板角点
	find4QuadCornerSubpix(gray,imgPoints,Size(5,5));//细化方格标定板角点坐r
	
	//生成棋盘格每个内角点的空间三维坐标
	Size squareSize = Size(10, 10);//棋盘格每个方格的真实尺寸
	vector PointSets;
	for (int j = 0; j < boardSize.height; j++)
	{
		for (int k = 0; k < boardSize.width; k++)
		{
			Point3f realPoint;
			//假设标定板为世界坐标系的z平面,即z=0
			realPoint.x = j*squareSize.width;
			realPoint.y = k*squareSize.height; 
			realPoint.z = 0;
			PointSets.push_back(realPoint);
		}
	}

	//输入前文计算得到的内参矩阵和畸变矩阵
	Mat cameraMatrix = (Mat_(3,3) << 532.016297,0,332.172519,
		0, 531.565159,233.388075,
		0, 0,1);

	Mat distCoeffs = (Mat_(1,5) << -0.285188,0.080097,0.001274,-0.002415, 0.106579);
	
	//用PnP算法计算旋转和平移量
	Mat rvec,tvec ;
	solvePnP(PointSets, imgPoints,cameraMatrix, distCoeffs,rvec,tvec); 
	cout << "世界坐标系变换到相机坐标系的旋转向量:" << rvec << endl;
	
	//旋转向量转换旋转矩阵
	Mat R;
	Rodrigues(rvec,R);
	cout << "旋转向量转换成旋转矩阵:" << endl << R << endl;
	
	//用PnP+Ransac算法计算旋转向量和平移向量
	Mat rvecRansac, tvecRansac;
	solvePnPRansac(PointSets, imgPoints,cameraMatrix, distCoeffs,rvecRansac,tvecRansac);
	
	Mat RRansac;
	Rodrigues(rvecRansac,RRansac);
	cout << "旋转向量转换成旋转矩阵:" << endl << RRansac << endl;

	waitKey(0);
	return 0;
}

4、差值法检测移动物体

单目相机标定、图像校正、单目位姿估计、差值法检测移动物体、稠密光流法跟踪移动物体_第11张图片

单目相机标定、图像校正、单目位姿估计、差值法检测移动物体、稠密光流法跟踪移动物体_第12张图片 

 

//差值法检测移动物体
int test4()
{
	//加载视频文件,并判断是否加载成功
	VideoCapture capture("F:/testMap/lolTFT.mp4");
	if (!capture.isOpened())
	{
		cout << "请确认视频文件是否正确" << endl;
		return -1;
	}
	//输出视频相关信息
	int fps = capture.get(CAP_PROP_FPS);
	int width = capture.get(CAP_PROP_FRAME_WIDTH);
	int height = capture.get(CAP_PROP_FRAME_HEIGHT);
	int num_of_frames = capture.get(CAP_PROP_FRAME_COUNT);
	cout << "视频宽度:" << width << "视频高度:" << height << "视频帧率 : "
		<< fps << "视频总帧数*" << num_of_frames << endl;

	//读取视频中第一帧图像作为前一帧图像,并进行灰度化
	Mat preFrame, preGray;
	capture.read(preFrame);
	cvtColor(preFrame, preGray, COLOR_BGR2GRAY);
	//对图像进行高斯滤波,减少噪声干扰
	GaussianBlur(preGray, preGray, Size(0, 0), 15);

	Mat binary;
	Mat frame, gray;
	//形态学操作的矩形模板
	Mat k = getStructuringElement(MORPH_RECT, Size(7, 7), Point(-1, -1));
	while (true)
	{
		//视频中所有图像处理完后推出循环
		if (!capture.read(frame))
		{
			break;
		}
		//对当前帧进行灰度化
		cvtColor(frame, gray, COLOR_BGR2GRAY);
		GaussianBlur(gray, gray, Size(0, 0), 15);

		//计算当前帧与前一帧的差值的绝对值
		absdiff(gray, preGray, binary);

		//对计算结果二值化并进行开运算,减少噪声的干扰
		threshold(binary, binary, 10, 255, THRESH_BINARY | THRESH_OTSU);
		morphologyEx(binary, binary, MORPH_OPEN, k);

		//显示处理结果
		imshow("input", frame); imshow("result", binary);

		//将当前帧变成前一倾,准备下一个循环,注释掉这句话为固定背景
		//gray.copyTo(preGray) ;

		//5毫秒延时判断是否推出程序,按ESC键退出
		char c = waitKey(5);
		if (c == 27)
		{
			break;
		}
	}
	waitKey(0);
	return 0;
}

5、稠密光流法跟踪移动物体

单目相机标定、图像校正、单目位姿估计、差值法检测移动物体、稠密光流法跟踪移动物体_第13张图片

 单目相机标定、图像校正、单目位姿估计、差值法检测移动物体、稠密光流法跟踪移动物体_第14张图片

 单目相机标定、图像校正、单目位姿估计、差值法检测移动物体、稠密光流法跟踪移动物体_第15张图片

 

//稠密光流法跟踪移动物体
int test5()
{
	VideoCapture capture("F:/testMap/lolTFT.mp4");
	Mat prevFrame,prevGray;
	if (!capture.read(prevFrame))
	{
		cout << "请确认视频文件名称是否正确" << endl;
		return -1;
	}
	//将彩色图像转换成灰度图像
    cvtColor(prevFrame, prevGray, COLOR_BGR2GRAY);

	while (true)
	{
		Mat nextFrame,nextGray;//所有图像处理完成后推出程序
		if (!capture.read(nextFrame))
		{
			break;
		}
		imshow("视频图像", nextFrame) ;
		
		//计算稠密光流
		cvtColor(nextFrame,nextGray,COLOR_BGR2GRAY); 
		Mat_ flow;//两个方向的运动速度
		calcOpticalFlowFarneback(prevGray,nextGray,flow,0.5,3,15,3,5,1.2,0);
		
		Mat xV = Mat::zeros(prevFrame.size(),CV_32FC1);//x方向移动速度
		Mat yV = Mat::zeros(prevFrame.size(),CV_32FC1);//y方向移动速度
		
		//提取两个方向的速度
		for (int row = 0; row < flow.rows; row++)
		{
			for (int col = 0; col < flow.cols; col++)
			{
				const Point2f& flow_xy = flow.at(row,col); 
				xV.at(row, col) = flow_xy.x;
				yV.at(row, col) = flow_xy.y;
			}
		}

		//计算向量角度和幅值
		Mat magnitude,angle;
		cartToPolar(xV, yV, magnitude,angle);
		
		//角度转换成角度制
		angle = angle * 180.0 / CV_PI / 2.0;//把幅值归一化到0-255区间便于显示结果
		normalize(magnitude,magnitude,0,255,NORM_MINMAX);
		
		//计算角度和幅值的绝对值
		convertScaleAbs(magnitude,magnitude); convertScaleAbs(angle, angle);
		
		//运动的幅值和角度生成HSV颜色空间的图像
		Mat HSV = Mat::zeros(prevFrame.size(), prevFrame.type());
		vector result;
		split(HSV,result); 
		result[0] = angle; //决定颜色
		result[1] = Scalar(255);
		result[2] = magnitude;//决定形态
		
		//将三个多通道图像合并成三通道图像
		merge(result,HSV);

		//讲HSV颜色空间图像转换到RGB颜色空间中
		Mat rgbImg;
		cvtColor(HSV,rgbImg,COLOR_HSV2BGR);//显示检测结果
		imshow("运动检测结果", rgbImg);
		int ch = waitKey(5);
		if (ch == 27)
		{
			break;
		}
	}

	waitKey(0);
	return 0;
}

你可能感兴趣的:(OpenCV学习笔记,opencv,图像处理)