赞
踩
若该文为原创文章,转载请注明原文出处
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/136293833
各位读者,知识无穷而人力有穷,要么改需求,要么找专业人士,要么自己研究
红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中…(点击传送门)
上一篇:《OpenCV开发笔记(七十四):OpenCV3.4.1+ffmpeg3.4.8交叉编译移植到海思平台Hi35xx平台》
下一篇:持续补充中…
相机标定,重映射可以进行插值映射从而矫正图像,这是一种方法,也有矩阵映射方法,本篇使用重映射方式解说畸变矫正的计算原理。
横向纵向区域固定拉伸:
横向纵向拉伸:
右下角拉伸:
标定相机需要做两件事:
Opencv提供了可以直接使用的矫正算法,即通过输入原始图像和由函数cv::calibrateCamera()得到的畸变系数,生成校正后的图像。(注意:这里可使用用cv::undistort()使用该算法直接完成所需任务,也可以使用函数cv::iniitUndistorRectifyMap()和cv::remap()来更有效的处理。
当进行图像矫正时,必须指定输入图像的每个像素在输出图像中移动到的位置,成为“矫正映射”(畸变映射)。
N x M的矩阵A中,重映射由双通道浮点数的N x M的矩阵B表示,对于图像A中的任意一点aPoint(i, j),映射为b1Point(i’, j’)和b2Point(i’, j’),在A中假设i=2,j=3,那么(假设重映射之后4.5,5.5)在B1中b1Point(i’, j’)值为4.5,b2Point(i’, j’)值为5.5,由于坐标是浮点数,那么需要插值得到整数位置以及中间过渡的区域颜色(平滑处理)。
双矩阵浮点数表示,N x M的矩阵A中,重映射由一对N x M的矩阵B和C描述,这里所有的N x M矩阵都是单通道浮点矩阵,在A中的点aPoint(i, j),重映射矩阵B中的点bPoint(i,j)存储了重映射后的i’ (映射后的i坐标), 重映射矩阵C中的点cPoint(i,j)存储了重映射后的j’(映射后的j坐标)。
映射由双通道有符号整数矩阵(即CV_16SC2类型)表示。该方式与双通道浮点数表示方式相同,但使用此格式要快得多(笔者理解:由浮点数插值改为整数插值,会要快一些,但是肯定双通道浮点数的表示方式图像效果会稍微好一些)。
在于得到插值的坐标系来映射新位置的x和y位置,要渐近等,所以本方法的核心关键在于得到标定后的矩阵,得到映射矩阵的方式可以自己写算法,也可以使用其他方式,后续文章继续深入这块。
void remap( InputArray src,
OutputArray dst,
InputArray map1,
InputArray map2,
int interpolation,
int borderMode = BORDER_CONSTANT,
const Scalar& borderValue = Scalar());
void OpenCVManager::testRemap2() { std::string srcFilePath = "D:/qtProject/openCVDemo/openCVDemo/modules/openCVManager/images/25.jpg"; // 步骤一:读取文件 cv::Mat srcMat = cv::imread(srcFilePath); // 缩放一下 int width = 400; int height = 400; cv::resize(srcMat, srcMat, cv::Size(width, height)); // 步骤二:映射矩阵 cv::Mat mapX; cv::Mat mapY; mapX.create(srcMat.size(), CV_32FC1); mapY.create(srcMat.size(), CV_32FC1); // 算法:这里400x400,将0~100放大至0~200,将100~400映射为200~400 // 算法:这里400x400,将0~100放大至0~200,将100~400映射为200~400 #if 0 for(int row = 0; row < srcMat.rows; row++) { for(int col = 0; col < srcMat.cols; col++) { // if(true) if(col < 200) { mapX.at<float>(row, col) = static_cast<float>(col * 1.0f / 2); }else{ mapX.at<float>(row, col) = static_cast<float>(100 + (col - 200) * 1.0f / 2 * 3); } // if(true) if(row < 200) { mapY.at<float>(row, col) = static_cast<float>(row * 1.0f / 2); }else{ mapY.at<float>(row, col) = static_cast<float>(100 + (row - 200) * 1.0f / 2 * 3); } } } #endif #if 0 for(int row = 0; row < srcMat.rows; row++) { for(int col = 0; col < srcMat.cols; col++) { // 这里是 0~200 缩放为 0~100 缩小 // 比例系数 if(col == 0) { mapX.at<float>(row, col) = static_cast<float>(col); }else if(col < 200) { mapX.at<float>(row, col) = static_cast<float>(col * 1.0f / 2 * (col * 1.0f / 199)); }else{ mapX.at<float>(row, col) = static_cast<float>(col * 1.0f / 2 * (col * 1.0f / 199)); } if(row == 0) { mapY.at<float>(row, col) = static_cast<float>(row); }else if(row < 200) { mapY.at<float>(row, col) = static_cast<float>(row * 1.0f / 2 * (row * 1.0f / 199)); }else{ mapY.at<float>(row, col) = static_cast<float>(row * 1.0f / 2 * (row * 1.0f / 199)); } } } #endif #if 1 for(int row = 0; row < srcMat.rows; row++) { for(int col = 0; col < srcMat.cols; col++) { // 比例系数 0~1.0(400~800)/400 mapX.at<float>(row, col) = static_cast<float>(col * ((col + 1 + 400) * 1.0f / 800)); mapY.at<float>(row, col) = static_cast<float>(row * ((row + 1 + 400) * 1.0f / 800)); } } #endif cv::Mat dstMat; cv::remap(srcMat, dstMat, mapX, mapY, CV_INTER_LINEAR, cv::BORDER_CONSTANT, cv::Scalar(255, 0, 0)); cv::imshow("1", srcMat); cv::imshow(_windowTitle.toStdString(), dstMat); cv::waitKey(0); }
上一篇:《OpenCV开发笔记(七十四):OpenCV3.4.1+ffmpeg3.4.8交叉编译移植到海思平台Hi35xx平台》
下一篇:持续补充中…
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/136293833
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。