逆透视请参考:智能车逆透视教程(含上位机、源码)_Wyean的博客-CSDN博客
去畸变+逆透视请参考:智能车去畸变+逆透视教程_LoseHu的博客-CSDN博客
去畸变:如下
1.简介
对于镜头而言,畸变是一种十分常见的现象,如本是方形的棋盘,边界被扭曲成曲线 。还有同样受到扭曲的赛道。
对于镜头而言,同等条件下一般度数越大,视野越广,所造成的畸变也越严重
编辑编辑
优点:
使用指针映射去畸变数组,只需要初始化映射一次,后续不需要时间
通用性强,可移植性高
保证视野不变条件下优化图像质量。
2.去畸变所需工具、环境
请确保过程中所有采集到的图片出自同一相机与镜头,且分辨率全部相同
1.棋盘标定图
(1)放置在同一个文件夹中(数量越多越好1,0张以上,推荐50张左右)
(2)需要将整个棋盘标定图拍摄进去,越清晰越好
编辑编辑
2.拍摄的赛道图,用于观察去畸变效果
仅用作观察效果,无特殊要求
编辑
3.去畸变上位机
在win7及以下系统无法打开
编辑
3.去畸变原理
不同的摄像头搭配不同的镜头,会有不一样的内参,所以,只需要提前测定相机内参即可在后续中方便去畸变。
具体原理请自行搜索图像处理-去畸变。
4.通过上位机求取相机内参
编辑
自动全图:如果勾选,去畸变的图会涵盖全图内容;若取消勾选,去畸变后的图会损失部分视野。注意:在桶形畸变下,如果勾选,会导致结果混乱,建议取消勾选。
横向、纵向角落点数:棋盘图中横向、纵向存在的角点数目,如下棋盘标定图中,横向为8,纵向为6,可认为是(方块数-1).
编辑
结果图宽度、高度:去畸变后的图片的宽度和高度,会自动生成,可以自行略微修改。
水平、竖直偏移:将图片在水平、竖直方向平移多少像素点。
最终内参会复制到您的剪切板中,如:
double cameraMatrix[3][3]={{296.482019,0.000000,152.664982},{0.000000,286.375269,104.540031},{0.000000,0.000000,1.000000}};
double distCoeffs[5]={-0.459946,0.283675,0.002304,0.002566,-0.109265};
int move_xy[2]={55,32};
注意事项:
1.请将棋盘标定图放在同一文件夹下,文件夹内最好不要有其他东西。
2.请保证拍摄的棋盘标定图质量,数量推荐在50张左右
5.在智能车上完成去畸变
和逆透视原理相同
求得矩阵后,就可根据矩阵,和结果图的坐标,计算出结果图中的某个点,在原图中的坐标。
但如果每获取到一帧图像,都进行一次映射,非常耗费时间。所以我们使用指针。
在初始化时只需要对指针地址进行一次映射,以后只需要调用指针数组,就可以获取到去畸变后的图。
cameraMatrix[3][3]、distCoeffs[5]、move_xy[2] 是你通过上位机求取的矩阵,在您的剪切板中。
ImageUsed[0][0]代表图像左上角的值
PER_IMG 为用来透视变换的图片,如果使用灰度图,那么ImageUsed就是灰度图的去畸变图,
如果使用二值化图,那么ImageUsed就是二值化的去畸变图
BlackColor的值为没有内容部分的灰度值。
只需要初始化时调用一次ImagePerspective_Init()函数,只需要初始化时调用一次!!!!一次就行!!!!!!!
代码如下:
// // Created by RUPC on 2022/10/14. // #define RESULT_ROW 100//结果图行列 #define RESULT_COL 114 #define USED_ROW 120 //用于透视图的行列 #define USED_COL 188 #define PER_IMG mt9v03x_image_dvp//mt9v03x_image_dvp:用于透视变换的图像 也可以使用二值化图 #define ImageUsed *PerImg_ip//*PerImg_ip定义使用的图像,ImageUsed为用于巡线和识别的图像 typedef unsigned char uint8_t; // 无符号 8 bits uint8_t *PerImg_ip[RESULT_ROW][RESULT_COL]; void ImagePerspective_Init(void) { static uint8_t BlackColor = 0; double cameraMatrix[3][3]={{296.482019,0.000000,152.664982},{0.000000,286.375269,104.540031},{0.000000,0.000000,1.000000}}; double distCoeffs[5]={-0.459946,0.283675,0.002304,0.002566,-0.109265}; int move_xy[2]={0,0}; /* 0:USED_COL * 1:USED_ROW * 2:fx =K.at<double>(0, 0) * 3:fy = K.at<double>(1, 1) * 4: ux = K.at<double>(0, 2) * 5: uy = K.at<double>(1, 2); * 6: k1 = .at<double>(0, 0), * 7: k2 = D.at<double>(0, 1), * 8: k3= D.at<double>(0, 4), * 9: p1 = D.at<double>(0, 2), * 10: p2 = D.at<double>(0, 3); */ /*********************Mat******************************/ double fx = cameraMatrix[0][0] , fy = cameraMatrix[1][1] , ux = cameraMatrix[0][2] , uy = cameraMatrix[1][2] , k1 = distCoeffs[0] , k2 = distCoeffs[1] , k3 = distCoeffs[4] , p1 = distCoeffs[2] , p2 = distCoeffs[3]; int move_x=move_xy[0], move_y=move_xy[1]; for (int i = -move_y; i < RESULT_ROW-move_y; i++) { for (int j = -move_x; j < RESULT_COL-move_x; j++) { double xCorrected = (j - ux) / fx; double yCorrected = (i - uy) / fy; double xDistortion, yDistortion; double r2 = xCorrected * xCorrected + yCorrected * yCorrected; double deltaRa = 1. + k1 * r2 + k2 * r2 * r2 + k3 * r2 * r2 * r2; double deltaRb = 1 / (1.); double deltaTx = 2. * p1 * xCorrected * yCorrected + p2 * (r2 + 2. * xCorrected * xCorrected); double deltaTy = p1 * (r2 + 2. * yCorrected * yCorrected) + 2. * p2 * xCorrected * yCorrected; xDistortion = xCorrected * deltaRa * deltaRb + deltaTx; yDistortion = yCorrected * deltaRa * deltaRb + deltaTy; xDistortion = xDistortion * fx + ux; yDistortion = yDistortion * fy + uy; if (i + move_y >= 0 && i + move_y < RESULT_ROW && j + move_x >= 0 && j + move_x < RESULT_COL) { if (yDistortion >= 0 && yDistortion < USED_ROW && xDistortion >= 0 && xDistortion < USED_COL) { PerImg_ip[i + move_y][j + move_x] = &mt9v03x_image_dvp[(int) yDistortion][(int) xDistortion]; } else PerImg_ip[i + move_y][j + move_x] = &BlackColor; } } } } /*ImageUsed[0][0]代表图像左上角的值*/ /*完成摄像头初始化后,调用一次ImagePerspective_Init,此后,直接调用ImageUsed 即为去畸变结果*/
屏幕显示去畸变后的灰度图DEMO:
int main(void) { All_Init();//屏幕、摄像头、以及其他外设初始化 ImagePerspective_Init(); while(1) { if (mt9v03x_finish_flag_dvp == 1) { uint8_t show[RESULT_ROW][RESULT_COL]; for(int i=0;i<RESULT_ROW;i++) { for(int j=0;j<RESULT_COL;j++) { show[i][j]=ImageUsed[i][j]; } } ips114_show_gray_image(0,0,show[0],RESULT_COL,RESULT_ROW,RESULT_COL,RESULT_ROW,0); mt9v03x_finish_flag_dvp = 0; } } }
6.资源文件
其中包含了测试图包
CSDN:https://download.csdn.net/download/wu58430/86399773
推荐github:https://github.com/wu58430/RUBO-IPM
如果只使用用途,下载github中Release即可。
现在已经完成了逆透视、去畸变、逆透视+去畸变的操作,除非程序有重大bug,后续不会考虑更新。此三种只是图片处理方法,如此软件只适用于简化和降低操作的门槛,以便大家共同进步,图像处理方法无好坏之分,但确实有精妙与粗糙之别。
版权声明:
此软件仅用于竞赛、学习交流,禁止任何商业用途,包括有营利性的、商业的教学指导活动。
7.更新日志
2022.8.23 修复了不同版本windows兼容问题
2022.8.27 修复中文路径、视图大小异常问题,缩小程序体积
2022.9.23 增加了彩色图像显示,输出格式改为数组
2022.10.7 代码迁移至QT6.3.1环境,加入去畸变,加入保存图片功能
2022.10.29 融合两种方法,修复保存图像色彩错误问题
标签:教程,r2,int,double,move,畸变,图像处理,RESULT From: https://www.cnblogs.com/RUBO/p/16854043.html