站点图标 AI技术聚合

Opencv之极坐标对图像进行变换

Opencv之极坐标对图像进行变换

学习资料参考:

张平.《OpenCV算法精解:基于Python与C++》.[Z].北京.电子工业出版社.2017.

Table of Contents

原理分析

与使用二维函数表示输入图像的像素一致,这里使用极坐标和笛卡尔坐标的一一对应来获得图像输出矩阵的每个像素值。

完成

#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace cv;
Mat polar(Mat I, Point2f center, Size size, float minr = 0, float mintheta = 0, float thetaStep = 1.0 / 4, float rStep = 1.0) {
	//构造全0矩阵,此处为列矩阵(可看作一条从中心点发出的射线的每一点r取值)
	Mat ri = Mat::zeros(Size(1, size.height), CV_32FC1);
	//列矩阵赋值为每个坐标点的r值
	for (int i = 0; i < size.height; ++i) {
		ri.at<float>(i, 0) = minr + i * rStep;
	}
	//由于宽度为150,那么将该列向量在x轴方向进行复制1440(360*4)次,即将输出图像的所有r值确定
	Mat r = repeat(ri, 1, size.width);
	//构建theta,此处构建的是行向量矩阵(可看作一个圆环的\theta取值范围)
	Mat thetaj = Mat::zeros(Size(size.width, 1), CV_32FC1);
	//行向量赋值为每个坐标点的\theta取值
	for (int j = 0; j < size.width; ++j) {
		thetaj.at<float>(0, j) = mintheta + j * thetaStep;
	}
	//在y轴方向进行复制150次
	Mat theta = repeat(thetaj, size.height, 1);
	//将极坐标转换为笛卡尔坐标
	Mat x, y;
	polarToCart(r, theta, x, y, true);
	//将坐标原点移动到中心点
	x += center.x;
	y += center.y;
	//最邻近插值
	Mat dst = 125 * Mat::ones(size, CV_8UC1);
	for (int i = 0; i < size.height; ++i) {
		for (int j = 0; j < size.width; ++j) {
			float xij = x.at<float>(i, j);
			float yij = y.at<float>(i, j);
			int neareastx = int(round(xij));
			int neareasty = int(round(yij));
			if ((0 <= neareastx && neareastx < I.cols) && (0 <= neareasty && neareasty < I.rows))
				dst.at<uchar>(i, j) = I.at<uchar>(neareasty, neareastx);
		}
	}
	return dst;
}
int main() {
	//读取图片
	Mat I = imread("p4.jpg", IMREAD_GRAYSCALE);
	if (!I.data)
		return -1;
	//极坐标变换
	float thetaStep = 1.0 / 4;
	//设置距离中心的最短距离
	float minr = 163;
	//设置输出图片的大小或者需要处理的圆环的大小
	//第一个参数为宽度,第二个参数为高度
	Size size(int(360 / thetaStep), 150);
	//进行圆环处理
	Mat dst = polar(I, Point2f(313, 313), size, minr);
	//沿水平方向的镜像处理
	flip(dst, dst, 0);
	//显示结果
	imshow("I", I);
	imshow("极坐标变换", dst);
	waitKey(0);
	return 0;
}

运行结果

原始图像

极坐标变换后的结果

注:由于代码中的具体参数与图片相关,这里对我的参数设计进行说明:

float minr = 163;
Size size(int(360 / thetaStep), 150);
Mat dst = polar(I, Point2f(313, 313), size, minr);

minr表示章节外围字符到章节中心的最短距离。
size(,150)该150为章印的字符的宽度。
Point2f(313, 313)为印章的中心坐标。
原图为616×616大小

但上述图片转换的并不美观,我们发现并不一定要360度,其实270度就够了,那么将度数的最小值设为-230即可,得到如下显示:

文章出处登录后可见!

已经登录?立即刷新
退出移动版