第五节-5.3.2图像去畸变

it2025-08-05  1

一、CMakeLists文件

cmake_minimum_required(VERSION 3.15) project(undistorImage) find_package(OpenCV REQUIRED) include_directories(${OpenCV_INCLUDE_DIRS}) set(CMAKE_CXX_STANDARD 14) add_executable(undistorImage main.cpp) target_link_libraries(undistorImage ${OpenCV_LIBS})

二、.cpp文件

#include <iostream> #include <opencv2//opencv.hpp>> #include <string> using namespace std; string image_file = "/home/zhangman/slambook2-master/ch5/imageBasics/distorted.png"; //本程序从公式出发手写去畸变,以便深入理解畸变。实际上OpenCV可以通过cv::Undistor()函数去畸变 int main() { //设定相机畸变参数 double k1 = -0.28340811,k2 = 0.07395907, p1 = 0.00019359, p2 = 1.76187114e-05; //设定相机内参 double fx = 458.654, fy = 457.296, cx = 367.215, cy = 248.375; //以8通道灰度图读取图片,imread()第二个参数对应的是读取方式,详情见下文 cv::Mat image = cv::imread(image_file,0); //获取图像高度rows,图像宽度cols int rows = image.rows,cols = image.cols; //定义一个Mat类型变量用于存储去畸变后的图像 cv::Mat image_undistored = cv::Mat(rows,cols,CV_8UC1); //逐个遍历像素去畸变 for(int v = 0; v < rows; v++){ for(int u = 0; u < cols; u++){ //计算图像坐标点(u,v)对应成像平面上的点坐标(x,y) double x = (u - cx) / fx, y = (v - cy) / fy; double r = sqrt(x * x + y *y); //计算畸变后成像平面上对应点(u,v)的坐标 double x_distored = x * (1 + k1 * r * r + k2 * r * r * r * r) + 2 * p1 * x * y + p2 * (r * r + 2 * x * x); double y_distored = y * (1 + k1 * r * r + k2 * r * r * r * r) + p1 * (r * r + 2 * y * y) + 2 * p2 * x * y; //计算畸变后(u,v)在图像坐标系上对应坐标值(u_distored,v_distorec) double u_distored = x_distored * fx + cx; double v_distored = y_distored * fy + cy; //如果畸变后像素在图像方位内,则将其映射到去畸变图像相应的坐标位置 if(v_distored > 0 && u_distored > 0 && u_distored < cols && v_distored < rows){ //image_undistored.at<uchar>(v,u)是获取图像在(u,v)处的灰度值 image_undistored.at<uchar>(v,u) = image.at<uchar>((int) v_distored, (int) u_distored); } else{ image_undistored.at<uchar>(v,u) = 0; } } } //打印去畸变前后图像 cv::imshow("image_distored", image); cv::imshow("image_undistored", image_undistored); cv::waitKey(0); cv::destroyAllWindows(); return 0; }

三、imread()第二个参数数值详解

/*第二个参数 * -1 8深度 原通道 * 0 8深度 1通道 * 1 8深度 3通道 * 2 原深度 1通道 * 4 原深度 3通道 * CV_LOAD_IMAGE_ANYDEPTH 返回图像的深度不变 对应 2 * - 如果设置,当输入具有相应深度时返回16位/32位图像,否则将其转换为8位。 * * CV_LOAD_IMAGE_COLOR 对应 1 * - 如果设置,则始终将图像转换为彩色图像 * * CV_LOAD_IMAGE_GRAYSCALE 对应 0 * - 如果设置,则始终将图像转换为灰度图像,位深=8bit 通道数=1(颜色变灰) * *CV_LOAD_IMAGE_UNCHANGED 对应 -1 * – 在每个通道中,每个像素的位深为8 bit,通道数(颜色)保持不变 * *CV_LOAD_IMAGE_ANYCOLOR 对应 4 * – 位深不变 , 通道数不变 * * 组合 * CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR – 位深不变,通道数变 (最真实图像) * * CV_LOAD_IMAGE_COLOR | CV_LOAD_IMAGE_ANYDEPTH – 位深不变,通道数=3(三通道) * * 如果输入有冲突的标志,将采用较小的数字值 */

四、opencv中Mat格式的数据访问.at

opencv3中图形存储基本为Mat格式,如果我们想获取像素点的灰度值或者RGB值,可以通过image.at(i,j)的方式轻松获取。

Mat类中的at方法对于获取图像矩阵某点的RGB值或者改变某点的值很方便,对于单通道的图像,则可以使用:

image.at<uchar>(i, j)

其中有一个要注意的地方是i对应的是点的y坐标,j对应的是点的x坐标,而不是我们习惯的(x,y)

来获取或改变该点的值,而RGB通道的则可以使用:

//这里的[0],[1],[2]对应RGB哪个通道和图片格式有关。 image.at<Vec3b>(i, j)[0] image.at<Vec3b>(i, j)[1] image.at<Vec3b>(i, j)[2]
最新回复(0)