有一篇论文介绍了几种展开的方法:

《基于3D全景视觉的智能三维立体摄像设备的设计》

原始全景图像,我从另一篇博客中下载下来的:

展示一下结果:

柱面展开图:

 

标题

 

 透视展开结果:

 

一  圆柱展开 

cylinderOn

void  cylinderOn(Mat Src)
{
	int nbottom = 0;
	int ntop = 0;
	int nright = 0;
	int nleft = 0;

	//根据边界值来获得直径
    nright = Src.cols;
	nleft = 0;
	nbottom = Src.rows;
	ntop =0;
	int d = min(nright - nleft, nbottom - ntop);

	Mat imgRoi;
	imgRoi = Src(Rect(nleft, ntop, d, d));
	imshow("ROI", imgRoi);
	imwrite("ROI.jpg", imgRoi);

	Mat dst(imgRoi.size(), CV_8UC3, Scalar(255, 255, 255));

	//建立映射表
	Mat map_x, map_y;
	map_x.create(imgRoi.size(), CV_32FC1);
	map_y.create(imgRoi.size(), CV_32FC1);
	for (int j = 0; j < d - 1; j++)
	{
		for (int i = 0; i < d - 1; i++)
		{
			map_x.at<float>(i, j) = static_cast<float>(d / 2.0 + i / 2.0*cos(1.0*j / d * 2 * CV_PI));//计算映射后的坐标
			map_y.at<float>(i, j) = static_cast<float>(d / 2.0 + i / 2.0*sin(1.0*j / d * 2 * CV_PI));
		}
	}
	//opencv自带的重映射函数
	remap(imgRoi, dst, map_x, map_y, CV_INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0));//用线性插值
	//重设大小
	resize(dst, dst, Size(), 2.0, 1.0);

	rotateImage(dst);//将图像旋转180度 映射之后是倒着的


	imshow("柱面投影结果", dst);
	imwrite("result.jpg", dst);
}

映射完之后旋转180度  rotateImage 

void rotateImage(Mat &dst)//旋转图像
{
	Point center(dst.cols / 2, dst.rows / 2);
	double angle = 180;//旋转180度
	double scale = 1.0;//不缩放
	Mat rotMat = getRotationMatrix2D(center, angle, scale);//计算旋转矩阵
	warpAffine(dst, dst, rotMat, dst.size());//生成图像
}

二 透视展开

double GetAngle(int i_ExpandWidth, int i_ExpandHeight,int outR)//获取角度
{
	double dw_Angle = (double)i_ExpandWidth / (double)outR;
	return dw_Angle;
}

int GetRadius(int i_ExpandWidth, int i_ExpandHeight)
{
	return i_ExpandHeight;
}

CvPoint FindPoint(double dw_Angle, int i_Radius, int innerR, int x_dot, int y_dot, IplImage* src)
{
	double x, y;
	i_Radius += innerR;
	x = i_Radius * cos(dw_Angle) + x_dot;//计算新的坐标 
	y = i_Radius * sin(dw_Angle) + y_dot;

	if (x < 0)x = 0;//判断是否超过边界 超过左边设置为0  超过右边 设置为右边坐标
	if (x >= src->width)x = src->width - 1;
	if (y < 0)y = 0;
	if (y >= src->height)y = src->width - 1;

	CvPoint pt = { (int)x,(int)y };//将点转化为整数坐标

	return pt;
}


void perspectOn(IplImage* src)
{

	int x_dot = 314;
	int y_dot = 295;
	int innerR = 50;
	int outR = 310;

	int Width = int(2 * PI * outR);   //展开图像的宽
	int Height = outR - innerR; //展开图像的高

	cout << "展开图像宽:" << Width << " 高:" << Height << endl;
	int i, j;
	double dw_Angle;
	int i_Radius;
	CvPoint pt;
	IplImage*dst;

	dst = cvCreateImage(cvSize(Width, Height), 8, 3);
	dst->origin = 0;
	cvZero(dst);

	uchar *dstData = (uchar*)dst->imageData;
	int step = dst->widthStep / sizeof(uchar);
	uchar *data1 = (uchar*)src->imageData;
	int step1 = src->widthStep / sizeof(uchar);
	int channels = src->nChannels;

	for (i = 0; i < Width-1; i++)
	{
		for (j = 0; j < Height-1; j++)
		{
			dw_Angle = GetAngle(i, j, outR);
			i_Radius = GetRadius(i, j);//获取半径
			pt = FindPoint(dw_Angle, i_Radius, innerR, x_dot, y_dot,src);//找转换后的坐标

			dstData[j*step + i * 3 + 0] = data1[pt.y*step1+pt.x*3+0];//重新赋值
			dstData[j*step + i * 3 + 1] = data1[pt.y*step1 + pt.x *3+ 1];
			dstData[j*step + i * 3 + 2] = data1[pt.y*step1 + pt.x *3+ 2];
		}
	}

	cvShowImage("透视", dst);
	cvSaveImage("dst.jpg", dst);
}

main函数调用

int main()
{
	Mat Src = imread("img.png");

	IplImage* src;
	src = cvLoadImage("img.png");

	cylinderOn(Src);
	perspectOn(src);

	waitKey();
	return 0;
}

 

GitHub 加速计划 / opencv31 / opencv
142
15
下载
OpenCV: 开源计算机视觉库
最近提交(Master分支:3 个月前 )
d9a139f9 Animated WebP Support #25608 related issues #24855 #22569 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake 2 天前
09030615 V4l default image size #25500 Added ability to set default image width and height for V4L capture. This is required for cameras that does not support 640x480 resolution because otherwise V4L capture cannot be opened and failed with "Pixel format of incoming image is unsupported by OpenCV" and then with "can't open camera by index" message. Because of the videoio architecture it is not possible to insert actions between CvCaptureCAM_V4L::CvCaptureCAM_V4L and CvCaptureCAM_V4L::open so the only way I found is to use environment variables to preselect the resolution. Related bug report is [#25499](https://github.com/opencv/opencv/issues/25499) Maybe (but not confirmed) this is also related to [#24551](https://github.com/opencv/opencv/issues/24551) This fix was made and verified in my local environment: capture board AVMATRIX VC42, Ubuntu 20, NVidia Jetson Orin. ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [X] I agree to contribute to the project under Apache 2 License. - [X] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [X] The PR is proposed to the proper branch - [X] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake 2 天前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐